🐢💨
Why Microservices
Make Systems Slower
Top 5 Performance Pitfalls & How to Fix Them
🎯 Interview Cheat Sheet
Network Latency Chatty APIs Sync Calls
Cascading Failures Over-Engineering
📋
The Interview Question
Understanding why microservices can hurt performance
❓ The Question
"Why do microservices make systems slower?"
✅ The Smart Answer Framework
Microservices trade performance for scalability & flexibility. The slowdown comes from:
Network overhead - Every service call crosses the network
Data serialization - JSON/Protobuf conversion takes CPU time
Distributed coordination - Services must wait for each other
Architectural complexity - More moving parts = more bottlenecks
MONOLITH (Fast) MICROSERVICES (Slower)
┌───────────────────────┐ ┌─────────┐ ┌─────────┐
│ │ │ Service │───▶│ Service │
│ Function A ──▶ B ──▶ C│ │ A │ │ B │
│ │ └────┬────┘ └────┬────┘
│ ~0.001ms per call │ │ 10ms │ 10ms
└───────────────────────┘ ▼ ▼
┌─────────┐ ┌─────────┐
│ Service │ │ Service │
│ C │ │ D │
└─────────┘ └─────────┘
Total: ~0.003ms Total: ~40ms+ (network overhead)
💡 Interview Tip
"The key insight is that microservices don't make systems inherently slower - poor design does. Let me walk you
through the 5 main pitfalls..."
1
Network Calls Everywhere
Every microservice talks over the network
🔴 The Problem
In a monolith, function calls are nanoseconds. In microservices, every call goes over the network - adding
milliseconds each time. More services = more latency.
📦 REAL EXAMPLE
E-commerce Order: Order → Inventory (10ms) → Payment (15ms) → Shipping (10ms) → Notification (5ms) =
40ms minimum in network travel!
✅ Solutions
Service Mesh (Istio/Linkerd) - Optimized service-to-service communication
gRPC over REST - Binary protocol, 10x faster than JSON
Colocate related services - Same datacenter/zone
API Gateway - Aggregate multiple calls into one
BEFORE: Multiple Network Hops AFTER: API Gateway Aggregation
Client Client
│ │
├──▶ User Service (10ms) │ Single Request
├──▶ Order Service (10ms) ▼
├──▶ Product Service (10ms) ┌─────────────┐
└──▶ Review Service (10ms) │ API Gateway │ ◀── Aggregates internally
└─────────────┘
Total: 40ms (4 round trips) Total: 15ms (1 round trip)
💡 Interview Tip
"Network latency is unavoidable, but we minimize it through strategic service placement, protocol choice (gRPC), and
request aggregation."
2
Too Many Small Requests
Chatty APIs kill performance
🔴 The Problem
When services make multiple tiny requests instead of fewer larger ones, network overhead compounds
dramatically. This is the "Chatty API" anti-pattern.
📦 REAL EXAMPLE
User Dashboard: Profile (5ms) → Settings (5ms) → Notifications (5ms) → Preferences (5ms) → Messages
(5ms) = 25ms instead of one 8ms bulk call!
❌ Chatty (Bad) ✅ Batched (Good)
GET /user/123/profile GET /user/123/dashboard
GET /user/123/settings
Returns all data in one call
GET /user/123/notifications
GET /user/123/preferences
1 request = 8ms
5 requests × 5ms = 25ms
✅ Solutions
Batch APIs - Combine related data in single endpoint
GraphQL - Client specifies exactly what data it needs
BFF Pattern - Backend-for-Frontend aggregates calls
Caching - Avoid repeated calls for same data
💡 Interview Tip
"I'd use the BFF pattern - a dedicated backend that aggregates multiple microservice calls into a single optimized
response for each client type."
3
Synchronous Call Chains
Waiting for other services blocks everything
🔴 The Problem
When Service A waits for B, which waits for C... the total response time is the sum of all waits. One slow
service delays everything.
SYNCHRONOUS (Slow) ASYNCHRONOUS (Fast)
Order ──▶ Inventory ──▶ Payment ──▶ Ship Order ─┬──▶ Inventory
10ms 15ms 10ms ├──▶ Payment
└──▶ Shipping
Total: 35ms (sequential) Total: 15ms (parallel, max of all)
─────────────────────────────────────────────────────────────────
With Message Queue (Async):
Order ──▶ 📨 Kafka ──▶ Inventory / Payment / Notification
Order returns immediately! Background processing.
✅ Solutions
Async messaging (Kafka/RabbitMQ) - Fire and forget, process later
Parallel calls - Use CompletableFuture/[Link] for independent services
Event-driven architecture - Services react to events
Timeouts + Circuit Breakers - Don't wait forever
📦 CODE EXAMPLE
Before: [Link]() → [Link]() → [Link]()
After: [Link](inventory, payment, shipping).join()
💡 Interview Tip
"I'd identify which calls are truly dependent vs independent. Independent calls run in parallel; for dependent flows, use
event-driven patterns with Kafka."
4
Cascading Failures
One slow service brings down everything
🔴 The Problem
When one service slows down, all services waiting on it slow down too. Threads pile up, memory exhausts,
entire system crashes.
THE DOMINO EFFECT:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Checkout │────▶│ Payment │────▶│ Bank │
│ Service │ │ Service │ │ API │
└─────────────┘ └─────────────┘ └─────────────┘
😰 😰 🐢
SLOW!
Threads waiting Threads waiting 3rd party delay
Bank API: 30s instead of 100ms → Payment exhausted → Checkout exhausted → 💥
✅ Solutions
Circuit Breaker (Resilience4j) - Stop calling failing service
Timeouts - Never wait forever (e.g., 2 second max)
Bulkheads - Isolate thread pools per service
Fallback responses - Return cached/default data when down
CIRCUIT BREAKER PATTERN:
┌────────────┐ ┌───────────────────┐ ┌────────────┐
│ Checkout │─────▶│ Circuit Breaker │─────▶│ Payment │
└────────────┘ └───────────────────┘ └────────────┘
│
CLOSED (normal) ←→ OPEN (fast fail)
│
Calls pass through OR Return fallback instantly
💡 Interview Tip
"I'd implement Circuit Breaker using Resilience4j. After 5 failures, circuit opens and returns fallback instantly instead of
waiting."
5
Over-Engineering
Too many services for simple tasks
🔴 The Problem
Breaking things into too many tiny services creates unnecessary network calls. Not everything needs to be a
microservice!
❌ Over-Engineered ✅ Right-Sized
User Profile split into: Single User Service with:
user-name-service All user-related data
user-email-service Cohesive bounded context
user-avatar-service Single network call
user-preferences-service 1 call, all data!
user-address-service
5 network calls for 1 profile!
✅ How to Right-Size Services
Domain-Driven Design - One service per bounded context
Team ownership - Service fits one team's responsibility
Data cohesion - Data that changes together stays together
Start monolith, extract later - Don't prematurely split
📦 GOOD SERVICE BOUNDARIES
✅ User Service - All user data (profile, settings, preferences)
✅ Order Service - Orders, line items, order history
❌ Email-Field-Service - Too granular!
💡 Interview Tip
"I follow the 'Two Pizza Rule' and DDD - if a team can't own a service end-to-end, the boundaries are wrong."
📊
Quick Reference
All 5 problems and solutions at a glance
# Problem Why It Happens Solution
1 Network Latency Every call crosses network gRPC, Service Mesh, Colocate
2 Chatty APIs Too many small requests Batch APIs, GraphQL, BFF
3 Sync Call Chains Services wait sequentially Async messaging, Parallel calls
4 Cascading Failures One slow = all slow Circuit Breaker, Timeouts
5 Over-Engineering Too many tiny services DDD, Right-sized boundaries
🛠️ Key Technologies to Mention
Category Technology Use Case
Protocol gRPC 10x faster than REST/JSON
Messaging Kafka / RabbitMQ Async communication
Resilience Resilience4j Circuit breaker, retry, bulkhead
Service Mesh Istio / Linkerd Traffic management
Caching Redis Reduce repeated calls
Tracing Jaeger / Zipkin Find bottlenecks
💡 Pro Tip
"Always mention you'd add distributed tracing FIRST to identify the actual bottleneck before optimizing."
🎯
Sample Interview Answers
Ready-to-use responses
❓ "Why are microservices slower than monoliths?"
"Microservices introduce network latency between services - what was a nanosecond function call becomes
a millisecond network call. But the tradeoff is worth it for scalability. We mitigate with gRPC, caching, and
async messaging."
❓ "How would you optimize a slow microservices system?"
"First, add distributed tracing to find the actual bottleneck. Then check for chatty APIs and batch them.
Convert synchronous chains to async where possible using Kafka. Finally, add circuit breakers to prevent
cascade failures."
❓ "When should you NOT use microservices?"
"For small teams, early-stage startups, or simple CRUD apps. The operational overhead isn't worth it. Start
with a well-structured monolith and extract services only when there's a clear scaling or team-boundary
need."
✅ The Perfect 30-Second Answer
"Microservices are slower because of network overhead, serialization costs, and distributed coordination. The
five main causes are: network latency, chatty APIs, synchronous call chains, cascading failures, and over-
engineering. We solve these with gRPC, batch APIs, async messaging with Kafka, circuit breakers, and proper
service boundaries using DDD."
The Golden Rule
"Microservices don't make systems slow —
poor design does."
Always measure first (tracing), then optimize the real bottleneck.
Good luck with your interview! 🚀