Skip to content
About
Main content

Push versus pull

Who decides when data moves, and why does that choice fix your latency-versus-throughput position?

This is the fourth primitive, and it applies to every pattern above.

Push: the decides when to deliver. It must therefore know each 's capacity, or it will overwhelm them. That means per-consumer state in the broker and a flow-control mechanism. (RabbitMQ's prefetch or QoS count is exactly this: a credit window of "at most N unacknowledged messages".) Benefits: no polling delay, the broker learns immediately when a consumer dies, and consumer code is simple.

Pull: the consumer decides when to fetch and how much. is structural: a busy consumer simply does not ask. The broker becomes almost stateless with respect to delivery. Costs: a floor equal to the poll interval, and wasted requests when idle.

The consequence that matters most:

A pulling consumer can say "give me up to 10 MB or 500 records, whichever comes first". It batches according to its own capacity, which is exactly the right party to decide. That is why high-throughput logs are pull-based. A pushing broker delivers as soon as it can, which is exactly right when you care about the tail latency of an individual message.

So the latency-versus-throughput position is largely determined by your push/pull choice. They are not independent knobs.

Long polling

Long polling is the obvious synthesis. The consumer sends a request, and the broker holds it open until data arrives or a expires. You get pull semantics (consumer-initiated, consumer-controlled batch size, natural backpressure) with push-like latency.

The cost is one held connection per idle consumer. This forces an event-driven server (a thread per connection dies at scale), and it adds a small periodic "empty response" cost at each timeout. SQS and the HTTP "hanging GET" both work this way. It is the right default for pull systems with bursty, low-volume traffic.

One more thing to know: push systems cannot easily be made to batch well, but pull systems can be made to have low latency (with long polling, or just a very short poll interval when the lag is zero). Because of this asymmetry, pull is the safer default when you do not yet know your traffic shape.