Producers push. Consumers pull. The queue absorbs the mismatch — until it doesn't.
What problem are we solving?
A web request handler that synchronously sends 100 welcome emails will block the user for as long as the slowest mail server takes. A message queue breaks that coupling: producers drop messages onto a queue in microseconds; consumers pull them off at their own pace. The queue absorbs bursts. The catch: if producers outpace consumers for too long, the queue grows unbounded — memory fills, latency climbs, and the system stops being "eventually consistent" and starts being eventually broken.
Live simulation
updates every 1s
Producers
30msg/s
Queue
0 deep
0limit 500
Consumers
0msg/s
Capacity3 × 15 = 45 msg/s0% used
Amber at depth 100+, red at 500+. Pause to inspect.
Controls
30 msg/s
3
15 msg/s
Live metrics
Queue depth0peak 0
Throughput0 msg/sof 45 capacity
Backlog growth+0 msg/s
Processing delay0.0s
Total produced0
Total processed0
Status
Stable — consumers keep up with producers.
What just happened?
Producers add 0 msg/s; consumers drain 0 msg/s. The queue is empty — consumers keep up with producers in real time. No backlog, no delay.
Try this
Find the breaking point
Producers just doubled their rate. Slide the producer rate up until the queue turns red, then add consumers until it stabilizes. This is the exact same trade-off real teams negotiate every day.
You can either add 2 more consumers at 15 msg/s each, or rewrite the consumer to be twice as fast. Which is cheaper to operate? Which is faster to deploy?
Key takeaway
A queue doesn't make a slow consumer faster — it makes the slowness tolerable by absorbing bursts. But every message that waits in the queue is latency a user will eventually pay. The queue is stable only when long-run producer rate ≤ long-run consumer capacity. Everything else is just how long the buffer buys you.