Microservices migrations are one of the most frequently undertaken and most frequently failed architectural initiatives in engineering. The pattern is remarkably consistent: a well-intentioned leadership decision to decompose a monolith, followed by eighteen months of distributed systems complexity, followed by a team that is slower than it was before and a system that is harder to reason about. The mistakes are predictable. And they keep repeating.
The Microservices Cargo Cult
The cargo cult problem in microservices adoption is that organisations adopt the artefacts of microservices — separate repositories, independent deployments, REST or gRPC interfaces between services — without understanding the conditions that make those artefacts valuable. Netflix, Amazon, and Google adopted microservices because they had specific scaling problems that a monolith could not solve and large enough engineering organisations to absorb the operational overhead. Adopting their architectural patterns without those conditions produces the overhead without the benefits.
The decision to migrate to microservices should be driven by a specific, articulable problem that a service-oriented architecture solves better than a well-structured monolith. Deployment bottlenecks caused by team size. Scaling requirements that differ dramatically between components. Regulatory requirements that mandate data isolation. These are valid reasons. “Microservices are best practice” and “our monolith feels messy” are not.
Mistake 1: Decomposing Before the Domain Is Understood
The most expensive mistake in a microservices migration is drawing service boundaries before the business domain is well understood. Service boundaries, once established, are extraordinarily expensive to change. APIs proliferate, data models diverge, deployment pipelines multiply. Getting the boundaries wrong means either building a distributed monolith — where services are technically separate but deeply coupled — or embarking on a second migration to correct the first one.
Domain-Driven Design offers the most rigorous approach to service boundary definition: identifying bounded contexts within the domain model and aligning service boundaries to those contexts. But the prerequisite for DDD-driven decomposition is genuine domain understanding — which takes time, requires close collaboration with domain experts, and cannot be rushed without producing poor boundaries.
The practical implication is that microservices migrations should begin with a domain modelling phase, not a technical decomposition phase. Teams that skip domain modelling in the interest of speed almost universally discover, twelve to eighteen months in, that their service boundaries do not reflect the actual structure of the business — and must be redesigned.
Mistake 2: Ignoring Operational Complexity
A monolith has one deployment pipeline, one logging destination, one monitoring dashboard, and one on-call runbook. Twenty microservices have twenty of each. This arithmetic is obvious in advance and consistently underestimated in practice. The operational overhead of microservices is not a rounding error — it is a fundamental shift in the engineering investment required to run the system reliably.
Teams that migrate to microservices without investing proportionately in observability, service mesh, distributed tracing, and automated deployment infrastructure end up with a system that is dramatically harder to operate than the monolith it replaced. Incidents that were previously debuggable by reading a stack trace now require reconstructing a distributed call chain across ten services, each with its own logging format and deployment cadence.
- Distributed tracing must be implemented before the first service is deployed, not retrofitted after the fact
- Centralised logging with structured log formats across all services is non-negotiable
- Service-level SLOs and alerting must be defined for each service independently
- Deployment automation must keep pace with service proliferation — manual deployments do not scale past five or six services
Mistake 3: Treating It as a One-Time Migration
Leaders who frame microservices migration as a project — with a start date, an end date, and a definition of done — create the wrong expectations and the wrong incentives. Microservices adoption is an architectural evolution, not a migration. The boundaries you draw today will need to be refined as the business evolves. New services will need to be created. Existing services will need to be merged or split as your understanding of the domain deepens.
Organisations that treat the migration as complete when the last component is extracted from the monolith stop investing in the practices — DDD, domain modelling, service governance — that make the architecture evolve well. The architecture then drifts toward a distributed monolith over time, as ad-hoc integrations are created outside the original design.
Mistake 4: Not Investing in the Platform Layer
Every service in a microservices architecture needs the same foundational capabilities: authentication, authorisation, logging, metrics, tracing, configuration management, secrets management, and deployment automation. Without a platform layer that provides these capabilities consistently, each team builds them independently. The result is inconsistent implementations, duplicated effort, and security vulnerabilities in the gaps.
The platform investment should precede or run parallel to the decomposition work. A platform team or platform capability — whether fully staffed or delivered through golden paths and shared tooling — is not optional for a successful microservices architecture. It is the foundation that makes the per-service delivery teams fast and the system coherent.
Mistake 5: Letting Conway’s Law Decide Service Boundaries
In organisations without deliberate domain modelling, service boundaries tend to align with team boundaries rather than domain boundaries. The backend team builds a backend service. The data team builds a data service. The result is a service architecture that mirrors the org chart rather than the business domain — and since the org chart rarely reflects the natural structure of the business, the service architecture is misaligned from the start.
Applying the Inverse Conway Manoeuvre — designing the organisation to produce the architecture you want rather than letting the organisation produce the architecture by default — requires deliberate leadership. It means structuring teams around business domains rather than technical layers, giving those teams end-to-end ownership of their domain including the service boundary decisions within it.
The Strangler Fig Pattern and Why Leaders Abandon It Too Early
The strangler fig pattern — gradually extracting services from the monolith while keeping the monolith running — is the most widely recommended approach to microservices migration for good reason. It is incremental, reversible, and testable. Each extraction delivers immediate value and can be validated before the next extraction begins.
The pattern fails when leaders lose patience with the incremental pace and pivot to a big-bang extraction. The strangler fig works precisely because it is slow and deliberate. Abandoning it midway leaves the organisation with the worst of both worlds: a monolith that is partially hollowed out and therefore harder to reason about, and a set of extracted services that are not yet mature enough to stand alone.
How to Know If Microservices Are Right for Your Stage
- You have specific, documented scaling requirements that differ significantly between components of your system
- Your monolith deployment is a genuine bottleneck because of team size and coordination overhead
- You have the engineering headcount and operational maturity to absorb distributed systems complexity
- Your domain is well-understood enough that you can draw stable service boundaries with confidence
- You have or can build a platform layer that provides consistent foundational capabilities to all services
Related Reading
Planning a microservices migration or stuck midway through one?
Our architects work with CTOs and engineering leaders to assess migration readiness, define domain boundaries, and build the platform foundations that make microservices work at scale.
Schedule a Consultation