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.