1. NSQ message ordering is odd. They don't provide any guaranties, but under high load it's more LIFO than FIFO and this is kinda unfair in our use case.
2. NSQ may suffer from network partitions. All cluster nodes are independent if your producer can access only node A, consumer can access node B, and node A can access B - messages will queue on node A and consumer will receive nothing until network partition gone.
3. NSQ stores messages in memory + disk (memory queue size is configurable). On node fail/restart you will lost all messages stored on memory. Small memory limit will nuke our disk. This was true few years ago, maybe this bit is improved now. But small memory limit is usually a bad thing, so you have to risk and find right balance. Not sure if NSQ handles somehow planned restarts with SIGTERM by flushing memory messages to disk. Actually I don't care anymore.
4. Strange go library solutions. They provide higher level consumer where you can write your own logic without worrying about connectivity part. But producer part you must implement connectivity logic by yourself (query nsqlookupd nodes to receive nsqd nodes, renew node list periodically, do loadbalancing, handle errors if node goes away during publish, etc). With 1.0.0 version they made unnecessary response struct change which means we need update all our 100+ services to support this change. This was so frustrating...
But NSQ has one really useful feature - pausing topics/channels. This really helps during critical situations when shit hits the fan.