Your system didn’t fail because of traffic. It failed because everything depended on one thing.
Rohan Malhotra
Staff Engineer @ Orbitly | Distributed systems, Go, Postgres | Writing about architecture tradeoffs
Your system didn’t fail because of traffic. It failed because everything depended on one thing.
Imagine you have a microservices architecture:
Booking Service
Payment Service
Notification Service
API Gateway
PostgreSQL + Redis
Everything works perfectly in staging. Then, one shared dependency starts responding slowly.
Suddenly:
Requests begin timing out.
Retries increase the load.
Connection pools get exhausted.
Healthy services start failing too.
This is how a small failure can become a system-wide incident.
The interesting part? Adding more servers might not fix the problem.
Sometimes, the real solution lies in architectural decisions:
→ Timeouts and bounded retries
→ Circuit breakers and bulkheads
→ Asynchronous processing with Kafka or another message broker
→ Caching strategies and graceful degradation
→ Idempotency for safe retries, especially in payment workflows
But every solution introduces trade-offs. A queue adds operational complexity. A cache introduces consistency challenges. A circuit breaker changes how failures are handled.
That’s what makes system design interesting: you’re not just designing how a system works. You’re designing how it fails.
Architecture question: If Redis became slow or unavailable in this system, what would you do first?
Fail fast with timeouts
Add a circuit breaker
Bypass the cache and fall back to the database
Something else
I’m interested in the reasoning behind your choice, especially for a production system.
#SystemDesign #DistributedSystems #Microservices #BackendEngineering
#systemdesign#distributedsystems#microservices#backendengineering
