ZMQ presents its own set of challenges, because it&#x27;s typically implemented as a linked-in native library, and this presents some interesting safety problems. In a previous life, we tried out ZMQ as a replacement to RabbitMQ for a use-case that we didn&#x27;t actually need long-term persistence for (real-time notifications), but we found Java, and Python ZMQ to provide exciting, hard-to-debug memory leaks, as well as plain segfaults. But, for some time I&#x27;ve been thinking about this, because having a smart client library does allow you to do really neat things efficiently (See: Fast Paxos: <a href="http:&#x2F;&#x2F;msr-waypoint.com&#x2F;pubs&#x2F;64624&#x2F;tr-2005-112.pdf" rel="nofollow">http:&#x2F;&#x2F;msr-waypoint.com&#x2F;pubs&#x2F;64624&#x2F;tr-2005-112.pdf</a>, Chubby: <a href="http:&#x2F;&#x2F;static.googleusercontent.com&#x2F;media&#x2F;research.google.com&#x2F;en&#x2F;&#x2F;archive&#x2F;chubby-osdi06.pdf" rel="nofollow">http:&#x2F;&#x2F;static.googleusercontent.com&#x2F;media&#x2F;research.google.co...</a>). I think the ideal model is to split up responsibilities in a distributed system between nodes that are smart clients, and the rest of the system, and in this, linked-in drivers can continue to utilize simple protocols like RPC + Protocol Buffers, and the actual system can use more complex, higher-level semantics, like dual-dispatch to smooth over latency. -- For whatever reason, people are more comfortable with running a totally foreign, binary library in their same process &#x2F; memory space, as opposed to running a binary and depending on it. -- I realize that operationally, it&#x27;s somewhat more complex to do the later, but that&#x27;s a question about maturity of methods. We&#x27;ve seen the Go community adopt this approach somewhat with things like the Packer plugin architecture (<a href="https:&#x2F;&#x2F;www.packer.io&#x2F;docs&#x2F;extend&#x2F;plugins.html" rel="nofollow">https:&#x2F;&#x2F;www.packer.io&#x2F;docs&#x2F;extend&#x2F;plugins.html</a>).