Glossary
Microservices architecture
Independent deployments can decouple changes and let different parts of a system scale separately. They also turn ordinary method calls into distributed communication, bringing latency, partial failures, and more complex consistency.
Short definition
A service boundary is defined by a system capability, not a line count.
A microservice is an independently deployable service that provides a cohesive capability and hides its implementation behind a contract. Its size is not judged by its number of classes or lines of code, but by its responsibility, autonomy of change, and whether a team can safely own it from development through production.
Microservices architecture is a property of an entire system and of the way teams work. Splitting one process into small modules, running them in containers, or adding an HTTP endpoint to each one is not enough. Meaningful boundaries follow the domain, patterns of change, team responsibilities, and operational needs.
What it solves
Parts of a large system can evolve and operate at different rates.
The approach can help when a single deployment constrains independent teams, or when particular capabilities have markedly different deployment, availability, and scaling requirements.
- deploying the catalogue independently without releasing the entire order system
- scaling product reads and payment processing separately
- clear ownership by a team responsible for a service’s code, data, deployments, and incidents
- isolating changes and some failures, provided callers know how to degrade gracefully
- gradually replacing a bounded capability instead of rewriting the entire system at once
Practical example
An order in a larger e-commerce platform
A platform may have a separate Catalogue service for products, an Order Service for orders, a Payment Service for payments, and an Inventory Service for stock. These boundaries do not come from simply dividing up tables: the Order Service owns ordering rules, the Payment Service owns payment processing, and the Inventory Service owns reservations against physical inventory. Each service is managed by a team that understands both its contract and its operation.
An API may synchronously verify information the user needs immediately. Once the order has been stored locally, the Order Service publishes an OrderCreated event through a message queue. The Inventory Service consumes it, creates a reservation idempotently, and publishes the outcome. If inventory is insufficient, a Saga Pattern can manage explicit state and compensation; a single database transaction spanning both services is generally unavailable.
Text diagram and accessible alternative
Frontend
→ API gateway (optional)
→ Order Service ──sync API──→ Payment Service
│
└── OrderCreated event ──→ Inventory Service
Each service: its own contract, data boundary, deployment, and monitoring
How it works
From a request through local changes to a distributed outcome
This flow is the text alternative to the diagram. An API gateway is one possible entry point, not a prerequisite for microservices architecture.
- Entering the system The frontend calls either a public service directly or an optional API gateway that handles routing and selected cross-cutting technical concerns. Domain rules should not accumulate there.
- A local decision The Order Service validates the request, applies its own rules, and stores the change atomically within its data boundary.
- Synchronous communication HTTP, gRPC, or another request–response protocol is appropriate when an answer is needed immediately. The caller must still expect timeouts, latency, and an unavailable peer.
- Asynchronous communication RabbitMQ or another broker can deliver an event without waiting for downstream work to complete. Redelivery, ordering, and failure paths each require deliberate design.
- Reaching the final state Services confirm local steps at different times. The system therefore tracks intermediate state, retries, compensation, and eventual consistency instead of pretending that one instantaneous transaction exists.
Key components and principles
Autonomy depends on the contract, data, and operations together.
A separate repository or container does not create a service by itself. The boundary should allow one capability to change without a coordinated release of many other parts.
Service boundaries
Domain-Driven Design can help distinguish bounded contexts and capabilities that change together. A bounded context is not automatically a microservice, however; it may remain a module within one deployable system.
Communication contract
A service hides its internal classes and database schema behind a versioned API or message schema. A REST API is one possible interface style, not the definition of a microservice.
Data and ownership
A service should be authoritative for its schema and writes. Database per service is a common principle of logical separation, not an instruction to buy a physical database server for every service; separate schemas or instances depend on the risks and operational requirements.
Deployment and ownership
Independent releases require compatible contracts, automated verification, rollback, and a team responsible for the service in production. Every service need not use a different language, and technology diversity carries its own cost.
Service discovery and routing
In a dynamic environment, callers need to locate a healthy service instance. DNS, an orchestrator, or a registry may provide discovery; this is neither a business boundary nor necessarily a bespoke product.
Observability
Centralised logs, metrics, and correlation IDs reconstruct one user journey across services. Distributed tracing shows a request’s path and the latency between services; without observability, incident response turns into guesswork across processes.
Benefits and limitations
Independence in one part of the system is purchased with distributed complexity.
Potential benefits
- independent deployment and scaling of genuinely separate capabilities
- clearer ownership of code, data, operations, and incidents by individual teams
- limiting the scope of some changes and failures when resilience is designed correctly
- the option to use a different technology where there is a concrete reason to do so
Limitations and common mistakes
- a network call may fail, become slow, or end with an unknown outcome
- a chain of synchronous calls increases latency and the risk of cascading failure
- changes spanning several services do not have a simple shared database transaction
- boundaries that are too fine-grained lead to many small network calls and coordinated deployments
- more pipelines, environments, secrets, alerts, and on-call responsibilities increase operating costs
- a shared database or library can secretly couple services despite their separate names
Microservices, monoliths, and other approaches
A well-structured monolith is often the better starting point.
A modular monolith has separate modules and clear internal interfaces, but is deployed as one unit and can use one local transaction. For a smaller team, an unsettled domain, ordinary load, or a system without distinct operational needs, it is usually easier to develop, test, debug, and run. A boundary can be extracted later if a demonstrable need for independent deployment emerges.
Docker is a possible deployment technology, not proof of an architecture: one monolith can run in a container, and a microservice can run without one. Likewise, a small class or in-process module is not a microservice because it has neither its own network contract nor an independent deployment lifecycle.
Clean Architecture concerns dependency direction inside an application, while microservices architecture divides a deployable system. They can be combined, but neither requires the other. SOA is a broader family of service-oriented designs; microservices usually emphasise finer domain boundaries, autonomous teams, and independent deployments, although no universal standard draws a precise line between the terms.
Resilience and operations
Every network boundary needs a plan for partial failure.
Successful operation depends as much on organisation, automation, and diagnostics as it does on splitting the code.
- define timeouts, bounded retries, and circuit breakers according to the type of operation
- use correlation IDs, centralised logs, metrics, alerts, and tracing for important flows
- design asynchronous consumers with idempotency and a traceable processing state
- keep local database transactions within one service and model eventual consistency or compensation across boundaries
- version contracts compatibly and verify interactions between producers and consumers
- track service ownership, service objectives, costs, and recovery procedures
- regularly assess whether a boundary still reduces coordination or merely moves it onto the network
Common questions
Microservices without technological shortcuts
Are microservices automatically better than a monolith?
No. They are worthwhile when independent deployment, scaling, and ownership outweigh the costs of a distributed system. For a smaller team and an unsettled domain, a well-structured monolith is usually safer and less expensive.
Does every microservice need its own database server?
No. What matters is that a service is authoritative for its data and that direct access by other services is restricted. A physical instance, cluster, or separate schema is chosen according to isolation, availability, and operating costs.
Is a Docker container a microservice?
No. A container is a way to package and run a process. It may contain a monolith, worker, or microservice; it does not define the architectural boundary or responsibility.
Must microservices communicate through REST APIs?
No. They can use synchronous HTTP or gRPC as well as asynchronous messages and events. The choice depends on the need for an immediate response, resilience, coupling, and required consistency.
How can I tell that services are too small?
Warning signs include numerous tiny network calls, changes that require several services to be released together, shared internal models, and unclear ownership. Capabilities that change together probably belong within one boundary.
How I choose an architecture in practice
I separate deployment boundaries only where they address a real need of the system and its team.
I consider the domain, data consistency, integration failures, observability, and operational capacity. A microservice is not an end in itself, and a well-structured monolith remains a first-class option.