What are common microservices anti-patterns and best practices?
Learn common microservices anti-patterns like the distributed monolith and shared database, plus best practices for resilient, deployable services.
Expected Interview Answer
Common microservices anti-patterns include the distributed monolith, a shared database across services, chatty synchronous call chains, and services split by technical layer instead of business capability. Best practices counter each: independent deployability, a database per service, asynchronous or well-bounded communication, and services aligned to bounded contexts.
A distributed monolith arises when services must be deployed together because they are tightly coupled, giving you all the operational cost of distribution with none of the independence. Sharing one database couples services through the schema and destroys autonomy. Long synchronous call chains create latency and cascading failures, which is why patterns like circuit breakers, timeouts, retries with backoff, and async messaging matter. Good design starts from business capabilities and bounded contexts, gives each service its own data, keeps APIs versioned and backward compatible, and invests early in observability, automated testing and CI/CD so services can truly evolve and deploy on their own.
- Genuine independent deployability and team autonomy
- Fault isolation so one failure does not cascade
- Clear ownership via bounded contexts
- Easier scaling of individual services
- Resilience through timeouts, retries and circuit breakers
AI Mentor Explanation
A distributed monolith is like fielders who can only move as one rigid block: spreading them out costs energy but you still cannot cover gaps independently. Good side-setting places each fielder for a specific role and lets the captain adjust one position without disturbing the rest, just as well-bounded services deploy and scale on their own.
Step-by-Step Explanation
Step 1
Spot the distributed monolith
If services must deploy together or share release cycles, they are coupled; break the coupling before adding more services.
Step 2
Give each service its own data
Replace shared databases with a database per service and integrate through APIs or events, not shared schemas.
Step 3
Design around bounded contexts
Split by business capability, not technical layer, so each service owns a coherent domain and its language.
Step 4
Harden communication
Add timeouts, retries with backoff, circuit breakers and prefer async messaging to avoid cascading failures.
Step 5
Invest in platform basics
Version APIs, automate CI/CD, and add centralized logging, metrics and tracing before scaling the service count.
What Interviewer Expects
- Recognition of the distributed monolith and shared-database anti-patterns
- Understanding of bounded contexts and database-per-service
- Resilience patterns like circuit breakers and retries
- The importance of independent deployability and CI/CD
- Awareness that observability is essential, not optional
Common Mistakes
- Splitting services too early or too finely without clear boundaries
- Sharing one database across many services
- Building synchronous chains with no timeouts or circuit breakers
- Splitting by technical layer instead of business capability
- Neglecting observability, versioning and automated testing
Best Answer (HR Friendly)
“The biggest mistakes with microservices are building services so tangled they must be released together, letting many services share one database, and chaining slow calls that fail together. The fixes are to align each service with a clear business area, give it its own data, and make communication resilient with timeouts and retries so services can be changed and deployed on their own.”
Code Example
const CircuitBreaker = require('opossum')
async function fetchPayment(id) {
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), 800)
try {
const res = await fetch(`http://payments/payments/${id}`, { signal: controller.signal })
if (!res.ok) throw new Error(`status ${res.status}`)
return res.json()
} finally {
clearTimeout(timer)
}
}
const breaker = new CircuitBreaker(fetchPayment, {
timeout: 1000,
errorThresholdPercentage: 50,
resetTimeout: 5000,
})
breaker.fallback(() => ({ status: 'UNKNOWN', degraded: true }))
module.exports = (id) => breaker.fire(id)Follow-up Questions
- How do you know if you have built a distributed monolith?
- Why is a database per service recommended?
- How do circuit breakers prevent cascading failures?
- What role do bounded contexts play in service boundaries?
- When is a monolith the better choice over microservices?
MCQ Practice
1. Which situation best describes a distributed monolith?
A distributed monolith has the operational cost of distribution but services cannot be deployed independently.
2. Why is sharing a single database across services an anti-pattern?
A shared schema couples services so a change for one can break others, destroying independent deployability.
3. Which pattern helps stop one slow service from freezing the whole request chain?
A circuit breaker trips after repeated failures and returns fast, preventing cascading failures across services.
Flash Cards
What is a distributed monolith? — Services that are so coupled they must be deployed together, incurring distribution cost without the independence.
Why database-per-service? — It removes schema coupling so each service owns its data and can evolve and deploy independently.
How do bounded contexts guide boundaries? — They align each service with one business capability and its own model, avoiding splits by technical layer.
What does a circuit breaker do? — It stops calling a failing dependency after a threshold, returning fast to prevent cascading failures.
Continue Learning
Related Interview Questions
What is service decomposition and how do you decide service boundaries?
hard
What is the difference between a monolithic and a microservices architecture?
medium
What is a bounded context in domain-driven design and how does it map to microservices?
medium
What is the CQRS pattern and when should you use it?
medium