A common misconception is that a circuit breaker protects your database.
It doesn't.
It only protects your application from repeatedly calling a dependency that is already known to be unhealthy.
What happens when Redis goes down?
Without a circuit breaker:
Request
│
Redis (500ms timeout)
│
DB
Every request:
- Waits for Redis to time out.
- Wastes network calls.
- Eventually hits the database anyway.
Enter the Circuit Breaker
After Redis fails repeatedly, the circuit opens.
Now requests become:
Request
│
Circuit Breaker
│
Fallback
Notice something?
The circuit breaker doesn't decide the fallback. It only decides:
"Should I even try Redis?"
So what is the fallback?
A production system usually follows this order:
Request
│
Circuit Open?
│
Yes
│
Local Cache?
│
Hit ─────────► Return
│
Miss
│
DB Rate Limiter
│
Allowed?
│
Yes ─────────► Database
│
No
│
Return 503
Why a DB Rate Limiter?
Suppose:
- Normal traffic: 100K RPS
- Redis serves 99K RPS
- Database handles 1K RPS
If Redis crashes and every request falls back to the database:
100K RPS
↓
Database 💥
Instead, protect the database:
if circuitBreaker.IsOpen() {
if localCache.Has(key) {
return localCache.Get(key)
}
if !dbRateLimiter.Allow() {
return 503
}
return db.Get(key)
}
Only a limited number of requests are allowed to reach the database. The rest fail fast, keeping the system alive.
Where is the DB Rate Limiter?
Not in the API Gateway.
The gateway only sees:
GET /users/123
It has no idea whether your service will:
- Query Redis
- Query Postgres
- Call Elasticsearch
- Read Kafka
The service itself knows when it's about to hit the database, so that's where the dependency-specific rate limiter belongs.
👉 Read: Database Rate Limiting: The Missing Piece After a Circuit Breaker
A circuit breaker and a rate limiter solve different problems.
- Circuit Breaker: Stop calling a dependency that is already failing.
- DB Rate Limiter: Protect the database from being overwhelmed when fallbacks occur.
In production, they almost always work together.
Top comments (0)