DevSecOps

From the monolith to microservices

Monolith or microservices? A comparison of both architectures, their strengths, their pitfalls (circular dependencies, latency, testing) and the criteria for choosing a modernisation path.

September 6, 20216 min
From the monolith to microservices
TL;DR
  • The monolith combines server code, client code and database in a single executable: simple to deploy at first, but hard to evolve.
  • Its main limits are slow startup, costly horizontal scalability, low reusability and risky debugging.
  • Microservices split the application into independent, loosely coupled services that can be deployed separately and scaled individually.
  • They also bring their own difficulties: circular dependencies, latency from remote calls and complex integration testing.
  • Patterns such as the strangler fig and Domain-Driven Design, combined with Kubernetes and distributed observability, structure a successful migration.

Introduction

Choosing between a monolithic architecture and microservices is one of the structuring decisions of a software project. The key to unlocking business agility lies in the data: you must assess the existing system to identify improvement opportunities before deciding.

Each model meets different needs. Moving to microservices too quickly can turn the pain of a monolith into a distributed hell. The challenge is therefore to understand the strengths and limits of each approach in order to make an informed choice.

In 2026, this decision is made in a very different tooling landscape than five years ago: Kubernetes and service meshes have become the default foundation, internal developer platforms industrialise service deployment, and distributed observability makes tracking a fragmented system far more practical than it used to be. This does not remove the trade-off - it shifts it.

The monolithic architecture: strengths and limits

In a monolith, the server-side code, the client-side code and the database are combined into a single executable. This kind of system is simple to deploy at first, which explains its popularity for quickly starting a project or launching a modest-sized application.

Why monoliths are appealing at first

A single code repository, a single build pipeline, a single environment to monitor: the initial cognitive load is low, and a small team can ship fast without investing in distributed infrastructure. Internal refactoring is also simpler, since the compiler or the IDE guarantees the consistency of the whole with every change.

Where the model breaks down at scale

As the application grows, its limits appear. Startup becomes slow because launch times depend heavily on the size of the code. Horizontal scalability requires replicating the entire application, which is expensive even when a single module concentrates the load. Strong coupling restricts code reusability, and debugging becomes harder: a single bug can paralyse the whole application. Build and deployment time also grows longer with every new feature added to the same executable.

The microservices architecture: decoupling for agility

The microservices approach splits the application into small services that run independently of one another. Coupling is low, which minimises dependencies between services, and each one can be deployed separately without redeploying the whole.

Autonomous services, deployed separately

Each service has its own lifecycle: its own repository, its own technology stack where justified, its own deployment cadence. A team can ship several times a day within its own scope without waiting for other teams' approval, which shortens the time between an idea and its release to production.

Business APIs orchestrating the whole

Exchanges rely on business-oriented APIs that ease integration between systems. Each service scales individually, offering fine-grained horizontal scalability: only the service under load gets replicated, not the entire application. Reliability is strengthened, provided remote calls are designed to tolerate partial failures - the failure of one service should not necessarily bring down the entire application.

The challenges of microservices: what isn't said enough

This flexibility has a downside, often underestimated at the moment of the initial decision.

Microservices anti-patterns: the traps that derail migrations
Related readMicroservices anti-patterns: the traps that derail migrationsMicroservices anti-patterns: distributed monolith, big bang data migration, nano-services, bad timeouts, reach-in reporting, the traps to detect and the fixes.Read the article

Circular dependencies and version conflicts

Circular dependencies can cause version conflicts between shared packages, especially when several teams evolve a common library at different paces. Without clear governance of interface contracts, a seemingly minor change in one service can silently break several consumers.

Latency, remote calls and integration testing

Latency increases when dozens, or even hundreds, of services communicate through remote calls, which slows down the overall system if call chains are not kept under control. Integration testing also grows more complex, since it requires running several services simultaneously to verify they work together correctly - a constraint that ephemeral test environments and contract testing ease without fully eliminating. Ignoring these difficulties means trading the pains of the monolith for the more insidious ones of a poorly mastered distributed system.

The patterns that structure a successful migration

A migration from monolith to microservices rarely succeeds through a brutal split. The most accomplished organisations rely on proven patterns to sequence the transformation.

Strangler fig and progressive decomposition

The strangler fig pattern consists of progressively migrating the traffic of a feature from the monolith to a new service, until the old code can be safely removed. This approach avoids the big-bang gamble - a complete, long and risky rewrite - in favour of an incremental path that can be paused or adjusted at any time.

Domain-Driven Design to trace the boundaries

Domain-driven design (DDD): principles, patterns and benefits
Related readDomain-driven design (DDD): principles, patterns and benefitsDomain-driven design principles: ubiquitous language, bounded contexts, aggregates, event storming. When to adopt DDD and the benefits you can expect.Read the article

Tracing the boundaries between services is often the most structuring decision of a migration: poorly drawn, it produces exactly the circular dependencies and chatty coupling that make microservices more painful than the monolith they replace. Domain-Driven Design's bounded contexts offer a framework for aligning this decomposition with real business boundaries rather than purely technical considerations.

Kubernetes, platform and observability: the 2026 toolset

The operational success of microservices depends heavily on the tooling around them.

Container orchestration and service mesh

Kubernetes has become the orchestration standard, complemented by service meshes that handle routing, resilience (retries, circuit breakers) and encryption of inter-service traffic without every team having to reimplement it. Internal developer platforms add a self-service layer that cuts the time needed to bring a new service to production, often from several weeks down to a few hours.

Distributed observability

Observability patterns for distributed systems: logs, metrics, traces and profiles
Related readObservability patterns for distributed systems: logs, metrics, traces and profilesLogs, metrics, traces and profiles: the observability patterns that make a distributed system understandable, with OpenTelemetry as the common standard.Read the article

A distributed system made of dozens of services can no longer be debugged with local logs alone: distributed tracing, which follows a request across every service it touches, becomes essential to understand where a slowdown or an error truly originates. Without this investment in observability, the operational complexity of microservices quickly outweighs the expected benefits.

Which model to choose

The monolith remains relevant for small teams, simple applications or projects that must be launched quickly. Microservices, on the other hand, are the right fit for complex applications that require robust scalability and rely on experienced teams able to handle their operational complexity.

There is no universal answer: the right choice depends on the context, the maturity of the teams, the available operating budget and the business objectives. An organisation that does not yet have a solid observability and automation culture often benefits from consolidating these foundations before multiplying the services it has to monitor. Some teams even opt for a pragmatic middle ground - a modular monolith, where internal boundaries prefigure a future split without immediately paying its operational cost - before moving to microservices once load or team size genuinely justifies it.

At Adservio, we support companies in assessing their existing systems and defining their architecture roadmap, from the monolith to modernise through to decomposition into microservices when it is justified, with particular attention paid to sequencing rather than a complete and risky switch.

MicroservicesMonolithArchitectureDevOpsScalabilityKubernetesDomain-Driven DesignObservability

GET THIS ARTICLE

Download the full article as a PDF to read offline or share it.

SHARE THIS ARTICLE

On LinkedIn, X or by email, or just copy the link.

STAY POSTED

Get our next analyses and field notes straight to your inbox.

TALK TO AN EXPERT

Put these ideas into practice

Talk to our engineers about how this applies to your platform, your data and your teams.

By submitting this form, you agree to our privacy policy.

Frequently Asked Questions

Slow startup that depends on the size of the code, costly horizontal scalability since it requires replicating the whole application, low reusability due to strong coupling, and risky debugging where a single bug can paralyse the whole.

By relying on proven patterns rather than a brutal split: the strangler fig pattern to progressively migrate traffic, and Domain-Driven Design to trace service boundaries along real business lines rather than purely technical considerations.

Circular dependencies and version conflicts between shared packages, latency from remote calls between many services, and the complexity of integration tests - difficulties that mature distributed observability helps keep under control.