Microservices is a software architecture style in which an application is built as a set of small, independently deployable services, each responsible for one business capability, running in its own process and communicating over the network. In software architecture, it stands opposite the monolith, where all functionality is built and released as one unit.
Each service owns its data and its release cycle, so a team can change, test and deploy it without coordinating a release of the whole system. This independence is the central benefit of microservices, and the network, data consistency and operational complexity it introduces are its central costs.
How a microservices architecture works
A microservices system divides the domain along business boundaries, often called bounded contexts in domain-driven design, rather than along technical layers. An online store might have separate services for catalog, cart, ordering, payment and shipping, each with its own code base, database and deployment pipeline.
Services communicate through well-defined APIs. Synchronous calls typically use HTTP with REST or gRPC, while asynchronous messaging through a broker such as Kafka or RabbitMQ lets services react to events without waiting for each other. An API gateway usually sits at the edge, routing external requests and handling concerns such as authentication and rate limiting.
Running many services requires supporting infrastructure: service discovery so that services can find each other, containers and an orchestrator such as Kubernetes for deployment and scaling, and centralized logging, metrics and distributed tracing to follow a request across service boundaries.
Core principles and their parameters
Several principles distinguish genuine microservices from a system that is merely split into pieces. The table summarizes them and the practical choices each involves.
| Principle | Meaning | Practical consequence |
|---|---|---|
| Independent deployability | A service ships without releasing others | Backward-compatible API changes are mandatory |
| Database per service | No shared tables between services | Cross-service queries need APIs or events |
| Single business capability | One service, one responsibility | Service boundaries follow the domain |
| Decentralized governance | Teams choose suitable tools | Platform standards limit sprawl |
| Design for failure | Any call may time out or fail | Timeouts, retries and circuit breakers |
| Team ownership | One team owns a service end to end | Team size often 5 to 9 people |
Service size is not measured in lines of code. A useful test is whether one team can understand, change and redeploy the service confidently within a short cycle; services that always change together are probably one service split too finely.
Microservices compared with other architectures
Microservices are one point on a spectrum of modularity and deployment granularity. The comparison below shows why many teams start with a well-structured monolith and extract services only when needed.
| Aspect | Monolith | Modular monolith | Microservices | Serverless functions |
|---|---|---|---|---|
| Deployment unit | Whole application | Whole application | Each service | Each function |
| Module boundaries | Often weak | Enforced in code | Enforced by network | Enforced by platform |
| Data consistency | Local transactions | Local transactions | Eventual consistency | Eventual consistency |
| Operational effort | Low | Low | High | Medium, platform-managed |
| Independent scaling | No | No | Yes | Yes, automatic |
| Best fit | Small teams, early products | Growing products | Many teams, large domains | Event-driven tasks |
Microservices are compatible with internal design approaches such as clean architecture and patterns such as dependency injection, which structure the code inside each service. The architecture style decides how the system is divided and deployed; those patterns decide how each part is organized internally.
When microservices are the right choice
Microservices pay off when organizational scale, not technical fashion, drives the decision. Conway’s law observes that system structure tends to mirror the communication structure of the organization, so the architecture works best when service boundaries match team boundaries.
| Situation | Recommendation | Reason |
|---|---|---|
| Single small team, new product | Modular monolith | Boundaries are still changing |
| Several teams blocked by shared releases | Extract services | Restores independent delivery |
| One component needs very different scaling | Extract that component | Scale only where needed |
| Strong need for cross-entity transactions | Keep together | Distributed transactions are costly |
| No automated deployment or monitoring | Build the platform first | Many services multiply manual work |
Migration from a monolith is usually incremental through the strangler fig pattern: new functionality and extracted capabilities are routed to services one at a time, while the monolith shrinks. A big-bang rewrite carries far more risk and rarely succeeds on schedule.
Risks and common mistakes
The most frequent failure is the distributed monolith: services that are deployed separately but must be released together because they share databases, libraries with business logic or tightly coupled synchronous calls. It combines the costs of both styles with the benefits of neither.
- Chatty synchronous chains: a request passing through five services multiplies latency and failure probability.
- Shared database: breaks independent deployment and hides coupling.
- Missing observability: without tracing, finding the cause of one slow request becomes guesswork.
- Ignoring data consistency: business processes spanning services need sagas or compensating actions instead of distributed locks.
- Premature splitting: boundaries drawn before the domain is understood are expensive to move later.
Each network call adds latency, typically around a millisecond or more within a data center, plus a chance of failure. Designs that favor asynchronous events and keep critical paths short remain resilient as the number of services grows.
In simple terms
Microservices means building one large application out of many small, separate programs that talk to each other. Each small program does one job, such as handling payments or showing products, and a dedicated team looks after it.
Compare a single large restaurant kitchen with a food hall. In the kitchen, everyone shares one space, so a problem at one station slows everyone. In a food hall, each stall runs on its own, can change its menu without asking the others and can stay open if a neighbor closes. The price is more coordination, because orders, deliveries and cleaning must now work across many independent stalls.
A practical example
A ticket-selling platform starts as a single application maintained by eight developers. After a few years, the company has about 60 engineers in seven teams, and every weekly release requires coordinating changes from all teams. A bug in the reporting module once delayed an urgent fix to checkout by several days.
The company extracts services gradually using the strangler fig pattern. Checkout and payment become the first services, each with its own database, followed by event search and notifications. When a large concert goes on sale, the checkout service scales to many more instances while the rest of the system stays unchanged.
After roughly a year, teams deploy their services several times a day without joint release meetings. The company also adds distributed tracing and a platform team, because diagnosing failures across ten services proved impossible without them. The outcome is faster delivery at the cost of higher operational effort, which the company considers worthwhile at its size.