
Microservice architecture is an approach to building large systems as independently deployable services.
Key takeaways
- Microservices are independently deployable services split along business capabilities.
- For early-stage products, a well-modularised monolith is usually the better starting point.
- Badly drawn boundaries create a distributed monolith; domain-driven design reduces that risk.
- Adding services before monitoring, CI/CD and resilience measures are in place multiplies problems.
In this article6 sections
Microservice architecture is an approach in which a large system is built not as a single unit (a monolith) but as a set of small services, each responsible for one business capability and developed and deployed independently. Orders, payments, inventory, notifications and user management can each be a service that owns its data and talks to the others through APIs or messages. Used well, it speeds up teams and makes the system more resilient; chosen at the wrong time, it multiplies complexity. In this article we look at when microservices make sense and how to build them properly.
Monolith vs. microservices: the key differences
A monolith is not a bad thing. Many successful products grow for years as a single, well-modularised application. The differences show up as the system and the team grow.
| Aspect | Monolith | Microservices |
|---|---|---|
| Deployment | The whole application at once | Each service separately |
| Scaling | The entire application | Only the service under load |
| Data | Usually one database | Each service owns its data |
| Failure impact | One bug can affect everything | Failures stay isolated when designed well |
| Operational load | Low | High: monitoring, networking, distributed debugging |
| Speed at the start | High | Lower |
When do microservices make sense?
Moving to microservices is as much an organisational decision as a technical one. If several of these signs appear together, it is a good time to consider splitting:
- Several teams work in the same codebase and keep waiting on each other's releases.
- One part of the system (search or payments, for example) has very different load and scaling needs from the rest.
- Even a small change in one module has to go through the whole application's long test and release cycle.
- It has become clear that some components need a different technology or release cadence.
For an early-stage startup or a product still finding its direction, starting with microservices is usually an unnecessary burden. In that case a modular monolith with clear boundaries in the code is the better choice, and it makes extracting services later much easier.
Drawing the right boundaries
The most common reason microservice projects fail is badly drawn service boundaries. Services should be split by business capability, not by technical layer ("database service", "API service"). The idea of a bounded context from Domain-Driven Design is the guide here: when "order" means something different to sales, the warehouse and accounting, those areas are likely candidates for separate services.
Services that must call each other synchronously on every request and share the same database tables are not microservices but a distributed monolith: all the problems of a monolith plus all the problems of the network.
Communication, data and consistency
Services talk to each other in two basic ways: synchronous calls such as REST or gRPC, and asynchronous communication through message queues or event streams. The asynchronous style couples services less tightly; when one service is temporarily down, the others can keep working.
Because each service owns its data, you cannot use classic database transactions across services. That is why a few patterns become important:
- Saga pattern: a multi-step business flow is defined with a compensating action for each step in case something fails.
- Outbox pattern: the data change and the event to publish are stored in the same local transaction, so events are never lost.
- Eventual consistency: agree up front that some screens may update a few seconds late and that this is acceptable for the business.
Operations: the hidden cost
Microservices move part of the complexity from the code into operations. A healthy microservice environment needs these foundations in place:
- Automated tests and a CI/CD pipeline for every service
- Containerisation and a consistent deployment platform (often Kubernetes or a managed alternative)
- Centralised logging, metrics and distributed tracing across services
- Resilience measures such as timeouts, retries and circuit breakers
- API versioning and contract tests between services
Without this groundwork, adding services quickly makes debugging and releases harder, not easier.
Conclusion
Microservice architecture is not a goal in itself; it is a tool that solves specific problems. The right decision becomes clear when team structure, scaling needs and operational maturity are weighed together. When migrating, the best path is usually not a big-bang rewrite but extracting the component that brings the most benefit first and moving step by step (the strangler fig approach). At Dijicrea we usually start new projects with a well-modularised structure and split out services once a real need appears and the boundaries are clear.

