Skip to content

System Design

Backpressure (Slow Down Producers)

O(1) time to check the buffer level and push or drain one item · O(capacity) space for the buffer, which stays bounded instead of growing forever.

The idea, in plain English

Picture pouring water into a funnel that drains slowly into a bottle. Pour faster than the funnel can drain, and water overflows everywhere. Backpressure is the funnel pushing back before that happens. A slow consumer tells a fast producer, 'I'm getting full — pause for a bit,' instead of silently overflowing or crashing. Once the consumer catches up and there's room again, it tells the producer it's safe to resume.

How it works

  1. 1Put a bounded buffer — a queue with a maximum size — between the producer and the consumer.
  2. 2Before the producer pushes a new item, check the buffer against a high-water mark — an upper threshold. If the buffer has reached that mark, tell the producer to pause instead of accepting more.
  3. 3As the consumer drains items from the buffer, the buffer shrinks. Once it drops back to a low-water mark — a lower threshold — tell the producer it's safe to resume pushing.

When you'd use it

Use backpressure once your app is popular and a fast producer — like an API taking in incoming events — can generate work faster than a slower consumer, like a database writer, can keep up. Without backpressure, the buffer between them grows without limit, and the whole process eventually runs out of memory and crashes.

Common beginner mistakes

  • Letting the buffer grow with no maximum size at all. That only delays the crash instead of preventing it, since memory use is still unlimited.
  • Using the same threshold to pause and to resume. The producer would flip between paused and resumed on every single item right at that boundary. Using a lower resume mark than the pause mark gives it breathing room instead.

Try it — edit and run

Click the code to edit · press ⌘/Ctrl+↵ to run

Editable code. Tab and Shift+Tab indent. Press Escape, then Tab, to move focus out of the editor.

Expected output — hit Run to try it
Pipeline: pause at 4 items, resume at 1
produce e1: accepted (buffer size: 1)
produce e2: accepted (buffer size: 2)
produce e3: accepted (buffer size: 3)
produce e4: accepted (buffer size: 4)
produce e5: dropped (buffer size: 4)
produce e6: dropped (buffer size: 4)
producer paused: yes
consumer drained: e1, e2, e3 (buffer size: 1)
producer paused: no
produce e7: accepted (buffer size: 2)

Not sure this is the right topic? See the learning paths → or where this leads →