When we talk about scaling systems, the default thought is:
“How do we handle more requests?”
But the better question is:
“What happens when we receive more than we can handle?”
That’s where backpressure becomes important.
Not as a buzzword.
As a stability mechanism.
The Real Problem
In any backend system, different components have different capacities.
- API receives 10k requests/sec
- Service layer handles 6k/sec
- Database handles 3k/sec
That gap doesn’t disappear — it accumulates.
It turns into:
- Growing queues
- Thread pool exhaustion
- Memory pressure
- High GC
- Increased latency
Eventually → failure.
Backpressure exists to prevent that.
So What Is Backpressure?
At its core:
Backpressure is a flow-control mechanism in which the consumer controls how much data it receives from the producer.
Instead of:
Producer → pushes endlessly
Consumer → keeps accepting
We get:
Consumer → “Give me 100. I’ll ask again when ready.”
That simple shift changes system behaviour completely.
This Is Not Just a Reactive Concept
Yes, it’s formally defined in the Reactive Streams specification
and implemented in frameworks like:
- Project Reactor
- RxJava
- Spring WebFlux
But the idea applies even in regular Spring Boot applications.
Think about:
- Tomcat thread pool → limited
- DB connection pool → limited
- CPU cores → limited
If incoming rate > processing rate, the excess work sits in memory.
That’s uncontrolled buffering.
Backpressure is about making that buffering intentional and bounded.
Push vs Pull (Practical View)
Without Backpressure
while(true) {
sendEvent();
}
Consumer side:
Queue keeps growing…
Memory increases…
Latency increases…
Nothing crashes immediately.
But performance degrades silently.
With Backpressure
subscription.request(50);
Producer:
Send exactly 50.
Wait for next request.
The system becomes predictable.
And predictability is what makes systems reliable.
The Important Insight
Backpressure is not about slowing down traffic.
It’s about aligning work with capacity.
If a service can process 2,000 requests per second,
it should not accept 10,000 and “hope for the best.”
That hope becomes technical debt.
Where This Matters in Real Systems
1. Kafka Consumers
If consumer speed < producer speed:
- Lag increases
- Memory grows
- Rebalances become frequent
Smart systems:
- Control poll size
- Pause consumption
- Scale consumers
That’s practical backpressure thinking.
2. Database Writes
If DB supports 2k writes/sec
but API accepts 8k writes/sec:
You don’t have a scaling problem.
You have a flow-control problem.
3. Reactive APIs
In Spring WebFlux, you can do:
Flux.range(1, 1_000_000)
.limitRate(100)
.subscribe();
It processes data in chunks instead of flooding the subscriber.
That’s backpressure applied.
Most systems don’t fail instantly.
They degrade first.
Final Thought
Scaling isn’t just about handling more.
It’s about knowing when to slow down.
Backpressure is simply this principle:
Never accept more work than you can process safely.
And once you start thinking that way, you design systems differently.
More stable.
More predictable.
And far less fragile under pressure.
Top comments (0)