Microservices Architecture: Benefits, Costs & When Not To
What microservices actually are, why teams adopt them, the real costs of a distributed system, and — the part interviewers love — when NOT to use them. Monolith vs microservices, from fresher to senior.
🔵 Fundamentals · Fresher-friendly → 🔴 goes deep
"Should we use microservices?" is one of the most over-asked — and over-answered — questions in software. Everyone's heard the word, few can explain the real trade-off, and plenty of teams adopt them for the wrong reasons and regret it. This guide explains what microservices actually are, why they help, what they cost, and — the part that impresses interviewers — when NOT to use them. Let's get it straight from the ground up.
Start with the monolith
A monolith is a single application — one codebase, one deployable unit, usually one database. All features (users, orders, payments) live and ship together. This is not a dirty word: monoliths are simple to build, test, deploy, and debug, and they're the right choice for most small-to-medium apps. The pain only starts at scale.
As the app and the team grow, a big monolith gets heavy: one tiny change means redeploying the whole thing; a bug in one corner can crash everything; you can't scale just the busy part; and dozens of developers stepping on the same codebase slows everyone down. That pain is what microservices are meant to relieve.
What a microservice actually is
🟠A microservice is a small service focused on one business capability (e.g. "Payments"), that is independently deployable and owns its own database. That last part is the non-negotiable rule: services do not share a database. If Orders needs user data, it asks the Users service via an API — it never reaches into the Users tables directly. This is what keeps services truly decoupled.
Why teams adopt them (the benefits)
- Independent deployment: ship the Payments service without redeploying everything. Faster, safer releases.
- Independent scaling: Search getting hammered? Scale only Search, not the whole app — cheaper and more precise.
- Team autonomy: small teams own services end-to-end and move in parallel without colliding in one codebase.
- Fault isolation: if Search crashes, Orders and Payments keep running (if you design for it).
- Tech flexibility: each service can use the language/DB that fits its job.
The costs (this is where seniors earn their stripes)
🔴 Microservices don't remove complexity — they move it from your code into the network. New problems you now own:
- Distributed system pain: network calls fail, lag, and time out. You need retries, timeouts, and circuit breakers everywhere.
- Data consistency: no cross-service transactions. Keeping data correct across services needs the Saga pattern and eventual consistency.
- Observability: one user action now spans many services, so you need centralised logging, metrics, and distributed tracing just to answer "why was this slow?"
- Operational overhead: dozens of services to deploy, monitor, and secure — usually pushing you into containers, orchestration (Kubernetes), and CI/CD maturity.
How services talk, find each other, and present one face
🟠Three pieces make a microservices system work:
- Communication: synchronous (REST or gRPC request/response) for "I need an answer now," or asynchronous (events on a queue) for "react whenever." Favour async events to keep services decoupled.
- Service discovery: services come and go and change addresses, so a registry (or the platform, e.g. Kubernetes DNS) lets them find each other by name, not hardcoded IPs.
- API gateway: a single entry point for clients that routes to the right service and handles cross-cutting concerns — auth, rate limiting, TLS — so clients see one API, not fifty.
When NOT to use microservices
🔴 The most senior thing you can say: most projects should start as a monolith. Microservices earn their complexity only when you have a large system and a large organisation — many teams that need to deploy and scale independently. For a small team or an early product, microservices add distributed-systems pain with none of the payoff; you'll move slower, not faster. The mature path is a well-structured (modular) monolith first, then extract services when specific, real pressures appear (a part that must scale alone, a team that needs independence). Adopt them to solve a problem you actually have — never for the résumé.
The interview-ready summary
"Microservices split an app into small, independently deployable services that each own their data and talk over APIs or events. You gain independent scaling and deployment and team autonomy; you pay with distributed-systems complexity — network failures needing retries/circuit breakers, no cross-service transactions so you use Sagas, and heavy observability and ops needs. Because of that, I'd start with a modular monolith and extract services only when a real scaling or team-autonomy pressure justifies it." That balanced answer — benefits, costs, and restraint — is exactly what separates senior judgement from hype."
What to read next
- Distributed Transactions & Saga — consistency across services
- API Design: REST, gRPC & GraphQL — how services talk
- Resilience: Retries, Timeouts & Circuit Breakers — surviving network failures
- ← The complete System Design guide (hub)