1. Extensive use of asserts in release builds terrifies me. It's meant to check for conditions that shouldn't happen, but I see users complaining about their apps aborting with assertion failures on ZMQ mailing lists and it comes up fairly frequently in Google. There are a fair bit of asserts for error codes returned from system calls. I don't want a critical process crash because I've used library in a wrong way in a completely different part of the application.
2. Only in 2.1 they've fixed the problem where some messages would not be flushed and be lost if you terminate the process too early. This seems like a fairly common bug for younger projects. Recommended workaround is... calling "sleep" before you exit, which is one of the deadly sins of multithreaded programming! This and above point convinces me that ZMQ isn't as mature enough for me to be comfortable with.
3. Transparent reconnection is good, but some of our applications need to quickly detect that other nodes in the system are missing, which forces me to implement off-band heartbeat mechanism.
4. Threading model seems a bit awkward to me (last I checked). First of all, let me state that I personally believe that a library starting threads behind your back is a Bad Thing (unless it's a framework). ZMQ uses a sender thread that you queue your messages into, yet it forces you to dispatch your receive loop by either blocking read or zmq_poll. If it already starts threads by itself, why not provide a callback?
5. Not really a problem, but a missing feature: no way to demultiplex messages from a stream of messages, so you have to implement it yourself. You can subscribe to a subset of messages on a socket, but can't subscribe to multiple subsets from a single socket.
1. The 0MQ devs originally got asserts backwards, using them to validate external input (e.g. on sockets) instead of internal consistency. We've been fixing this for a year or two now, and it's pretty good. You'll get assertion failures if you e.g. use sockets from multiple threads. Not so much if you pass bad stuff onto sockets.
2. 2.1 was a great step forwards, and the use of "sleep" was in toy examples. Real networking apps tend to run forever, so this message loss at exit wasn't a big deal. You're right that the product is still young.
3. Totally agreed, this lack of peer presence detection is annoying, and the source of some debate on the lists.
4. Threading model works fine for me, I've used it extensively. A usable reactor is a hundred lines of code, no more. See the libzapi zloop reactor, in C, for example.
5. Demultiplexing sounds like useful functionality but should probable sit above sockets.
We evaluated using ZeroMQ for inter-shard communication in our distributed database engine, and while ZeroMQ had a lot going for it, in the end everyone on the team was so frustrated with attempting to reproduce corner case assertions and debugging ZeroMQ internals that we decided to bid it good riddance.
We were working towards a deadline, and ZeroMQ in the end proved counterproductive towards that goal; during the time we used it, we ran into some half a dozen different ZeroMQ asserts, some of them very difficult to reproduce, and of which I believe we managed to solve or work around only two or three.
Some of the problem may be in expectations. If you go in expecting it to be a mature and solid black-box solution (as its versioning might seem to indicate), you may be expecting too much. If you mentally prefix a '0.' to the version number and think of it as fast-evolving alpha software, you'll be happier.
I still believe the concepts behind ZeroMQ to be viable and laudable ones. We may reevaluate it in the future, but not anytime soon.
I use tons of debug asserts in my code, but I'm slowly coming to the conclusion that asserts enable lazy coding. Most asserts should probably be replaced with proper logging and error codes.