← All posts
5 min read

Backpressure: Keeping Overload Visible and Bounded

#technology#backpressure#overload#systems-at-scale
📑 On this page

When work arrives faster than a system can complete it, the excess must go somewhere.

Without a deliberate policy, it accumulates in memory, threads, connections, queues, retries, and user waiting until the system collapses.

Backpressure communicates or enforces that producers slow down when downstream capacity is exhausted.

Healthy overload behavior is bounded, visible, and connected to priority.

A concrete example: a streaming consumer

A consumer can process 100 records per second.

Instead of accepting an unlimited stream, it requests only the next 200 records. As it completes work, it requests more.

The producer cannot fill memory with an unbounded backlog.

Capacity mismatch

If average arrival rate exceeds average service rate, backlog grows indefinitely.

A temporary burst can be buffered if:

  • capacity catches up later,
  • queue is large enough,
  • and waiting deadline remains acceptable.

Backpressure cannot create capacity; it controls demand and failure.

Bounded queues

Every queue should have a limit based on:

  • memory,
  • storage,
  • maximum useful age,
  • and recovery time.

When full, the system must block, reject, drop, or redirect.

"Unlimited" means the failure moves to a less controlled resource.

Push and pull

In a push model, producers send work and need explicit rejection or flow-control signals.

In a pull model, consumers request only what they can handle.

Pull naturally expresses demand but still needs limits on outstanding work and retries.

Reactive streams

Some stream protocols let subscribers request a number of items.

The publisher emits no more than requested. Backpressure becomes part of the interface rather than an implementation detail.

Every intermediate operator must honor the signal.

TCP flow control

TCP has network-level flow control: a receiver advertises how much data it can buffer.

This protects bytes in one connection, not application capacity across requests. A server can accept bytes while being unable to process expensive work.

Application-level backpressure is still needed.

Admission control

Admission control decides whether new work enters.

It can use:

  • concurrent request limit,
  • queue capacity,
  • resource estimate,
  • tenant quota,
  • and service health.

Rejecting early preserves capacity for accepted work.

Rate limiting

Rate limits bound requests over time.

They protect fairness and cost but may not reflect current saturation. A normally safe rate can still overload a degraded dependency.

Combine static quotas with dynamic capacity signals.

Concurrency limits

Limiting in-flight operations can protect:

  • database connections,
  • memory,
  • external APIs,
  • and thread pools.

When the limit is reached, queue briefly or reject with retry guidance.

Adaptive concurrency can adjust based on observed latency.

Load shedding

Load shedding intentionally drops or rejects lower-value work.

Examples:

  • disable recommendations,
  • sample analytics,
  • reject expensive reports,
  • return cached data,
  • or refuse new sessions.

Shedding preserves core functions during overload.

Priority

High-priority work should not be trapped behind large low-priority batches.

Use:

  • separate queues,
  • weighted scheduling,
  • reserved capacity,
  • deadlines,
  • and aging.

Strict priority can starve ordinary users.

Deadlines

Work that cannot finish before its deadline should not consume scarce capacity indefinitely.

Propagate deadlines through queues and service calls, discard or compensate expired work safely, and distinguish expiration from successful cancellation. Processing an obsolete search request or notification after the user has moved on can delay work that still matters.

Producer cooperation

Backpressure is strongest when the producer can change behavior:

  • lower concurrency,
  • reduce batch creation,
  • pause polling,
  • or reject upstream input.

If producers ignore the signal, the consumer needs enforced admission control rather than a polite metric.

Fairness

One large tenant can consume all shared capacity.

Per-tenant quotas, weighted fair queues, and isolation prevent noisy neighbors.

Fair does not always mean equal; plans or workloads may have agreed weights.

Retry storms

Rejected or timed-out clients may retry immediately, increasing overload.

Return:

  • clear status,
  • Retry-After,
  • idempotency support.

Clients need bounded exponential backoff and jitter.

Queue age

Queue length alone is misleading because job sizes differ.

Oldest-message age and expected completion deadline show user impact more directly.

A small queue of hour-long jobs can be worse than a large queue of tiny jobs.

Little's law

Under stable conditions:

items in system = arrival rate × average time in system

If arrival rate stays constant and latency doubles, in-flight work doubles.

This relationship helps connect queue size, throughput, and delay.

Cascading failure

One slow dependency causes callers to hold resources longer.

Their queues fill, retries rise, and upstream services become slow too.

Timeouts, concurrency limits, circuit breakers, and load shedding contain the cascade.

User feedback

Overload should produce honest behavior:

  • "Report queue is full; try later."
  • "Your export is queued and expected in 20 minutes."
  • "Recommendations are temporarily unavailable."

Silence causes repeated clicks and more traffic.

Autoscaling

Autoscaling can add consumers, but startup takes time and downstream limits remain.

Backpressure protects the system while scaling reacts. Maximum scaling bounds cost and protects dependencies.

They are complementary controls.

Observability

Track:

  • arrival and completion rate,
  • queue length and age,
  • rejection,
  • concurrency,
  • resource saturation,
  • retry traffic,
  • and work by priority or tenant.

Alert before buffers reach irreversible collapse.

Testing overload

Test:

  • gradual demand,
  • sudden spike,
  • slow dependency,
  • retrying clients,
  • full queue,
  • priority behavior,
  • and recovery.

Verify core functions remain usable and backlog drains after demand falls.

Knowledge check

  1. Why does sustained arrival above service rate create unbounded backlog?
  2. How do pull systems express backpressure?
  3. Why is TCP flow control insufficient for application work?
  4. How does load shedding preserve service?
  5. What does Little's law connect?

The one idea to remember

Backpressure keeps overload from becoming invisible accumulation. Bound queues and concurrency, reject early, signal retry responsibly, protect priority and fairness, shed optional work, and monitor arrival, completion, age, and saturation as one control loop.