I just mean that since a client has to coordinate action across multiple connection (especially about the RDY count), it seems that connections can't live in their own greenlets without a lot of extra coordination.

Yes. The event loop's going to know when there's more data to be read, and so the client will ask the appropriate connection to do some reading. Rather than have the client object keep track of all this state, it seems that the connection should accumulate whatever's read into a buffer. If one or more entire messages have been read into that buffer, the resulting messages could be returned. If not, then none.

FWIW, I've pushed a better articulation of what I mean. [Here](https://github.com/dlecocq/nsq-py/blob/master/nsq/client.py#L59) the client figures out which connections are ready to have some data read from, and then accumulates all the read messages from all the connections. Then, in the [reader `__iter__`](https://github.com/dlecocq/nsq-py/blob/master/nsq/client.py#L105), they're yielded as they come in. Under the hood, they might come in with a lot of small partial reads or large batches, but at the reader `__iter__` point, that detail is abstracted away.