Monolith vs Microservices — Architecture Decision for the Mid-Market 2026

Software Development · May 2026 · 14 min read

← Part of the Software Development Guide
Mina Choi By Mina Choi · Reepa Solutions

Between 2015 and 2022, the answer to virtually every architecture question was taken for granted: Microservices. Today, in 2026, the pendulum has swung back significantly. Amazon Prime Video migrated a prominent video-monitoring pipeline from serverless microservices back to a monolith and saved 90 percent in infrastructure costs. Shopify, one of the loudest advocates, publicly describes its core system as a Modular Monolith. Even Netflix is walking back its own microservice cult in recent talks. For German mid-sized companies typically working with 10 to 50 developers, this shift is doubly relevant: first, most microservice migrations of recent years were launched far below the threshold where they actually make sense; second, the ongoing extra costs can no longer be justified with "that's what the big players do," because the big players themselves are reversing course. This article takes an honest look at the options — classic monolith, Modular Monolith, and true Microservices — and shows when each approach is genuinely the right fit. For context within the overall strategy, see our Software Development Guide for Mid-Sized Businesses.

The Reality in 2026: The Pendulum Swings Back

The "Microservices everywhere" trend shaped many architecture decisions between 2015 and 2022 that are now being corrected at great expense. Three observations from our consulting practice summarize the current situation. First: companies with fewer than 30 developers are running microservice landscapes with considerable overhead — service mesh, distributed tracing, dedicated platform teams — without the business logic justifying that complexity. Second: many "Microservices" in practice are really distributed monoliths — services that communicate over the network but are so tightly coupled that every change requires synchronizing multiple repositories and multiple deployments. Third: the operational costs of distributed systems — observability, availability, consistency, inter-service security — are massively underestimated in most business cases.

At the same time, the software industry has developed more precise vocabulary in recent years. Instead of the binary choice "monolith or microservices," we now recognize at least three clearly distinguishable architecture styles: the organically grown classic monolith, the Modular Monolith based on Domain-Driven Design principles, and true Microservices. The decision is not a black-and-white comparison but a question of maturity. For most German mid-sized companies, the Modular Monolith is today the sensible target state — and it typically remains so for several years.

The Classic Monolith — Pros and Cons

The classic monolith is an application deployed as a single artifact, but internally it has no enforced module boundaries. Database access, business logic, and presentation layer often crisscross each other, grown organically over the years. The perception of this architecture is distorted — it has real strengths that were readily overlooked in the microservice hype.

AspectStrengthWeakness
Development speed at the startVery high — all components in the same process, simple build, one repositoryDecreases with code size if no module boundaries are enforced
OperationsOne deployment, one log file, one health check — trivial compared to distributed systemsFull deployment on every change; longer downtimes for large applications
Transactional consistencyACID transactions across the entire database; no distributed consistency neededDatabase becomes a bottleneck under extreme load
Onboarding new developersOne codebase, one setup, one local dev serverHard to navigate at several hundred thousand lines of code
RefactoringCompiler or type-checker verifies all call sites synchronouslyWithout clear boundaries, hidden dependencies accumulate

The real weakness of the organically grown classic monolith is not the architecture itself but discipline: without enforced module boundaries, a spaghetti structure emerges over the years where every change triggers side effects in unexpected places. This is precisely where the Modular Monolith comes in.

Modular Monolith — The Underrated Sweet Spot

A Modular Monolith is a single deployable artifact — like a classic monolith — but internally divided into strictly bounded modules that communicate only through defined interfaces. The separation is not enforced by developer goodwill but technically: via Maven or Gradle modules, Go packages with internal protection, .NET project references, or architecture linters like ArchUnit or Dependency-Cruiser. Anyone who creates a cross-module dependency that does not go through the defined API fails at build time, not just at code review.

Two architecture styles provide the right conceptual foundation for a Modular Monolith. First, hexagonal architecture, which strictly separates business logic from the outer ring of adapters — database, HTTP, message bus — making domain code testable independently of infrastructure. Second, Domain-Driven Design with its central concept of Bounded Contexts: each module is a Bounded Context with its own language, its own data ownership, and explicit interfaces to other contexts.

From our consulting practice: in more than 80 percent of architecture audits with mid-sized clients, our recommendation is to first transform the existing monolith into a clean Modular Monolith rather than undertaking a microservice migration. The advantages are tangible. Module boundaries already deliver 80 percent of the maintainability benefits that Microservices promise — without the operational overhead. Database transactions remain ACID; no Saga pattern required. Refactoring is compiler-assisted. The module structure is simultaneously perfect groundwork for a later Strangler Fig extraction of individual scaling-critical Bounded Contexts — ready and waiting should it ever be needed.

Microservices — When Truly Necessary

Microservices have legitimate use cases. The following list captures the situations in which the extra costs of distributed systems are demonstrably justified:

Outside these scenarios, the effort is rarely justified. A rule of thumb from our practice: if you cannot clearly identify which specific business bottleneck Microservices will solve, you are building a solution to a problem you do not have.

Request a Free Architecture Assessment

Are you facing the decision between monolith, Modular Monolith, or Microservices? We offer a free 30-minute initial consultation — we assess your current codebase, team topology, and scaling requirements and deliver an honest recommendation with a rough cost estimate.

Request a free architecture assessment

Service Mesh and API Gateway Overhead

Once more than a handful of services are in play, service mesh and API gateway come into the picture. A service mesh — Istio, Linkerd, or similar — handles mTLS, retry logic, traffic shaping, and telemetry between services. An API gateway — Kong, Apigee, AWS API Gateway — handles authentication, rate limiting, and versioning at the outer edge. Both are powerful but expensive to set up and operate. An Istio cluster typically requires a dedicated platform engineer position because the sidecar proxies add CPU and memory overhead per pod and configuration errors can introduce subtle latency and security issues.

For mid-sized clients running fewer than 30 Microservices, we typically recommend a lightweight approach: no full service mesh, but a simple API gateway at the outer edge and library-based retry and mTLS logic internally. If you do not need the service mesh, do not set it up — the ongoing operational burden is considerable.

The Database-per-Service Problem

One of the hardest consequences of a true microservice architecture is data ownership per service. The mantra is: each service has its own database; other services may not access it directly, only through the API. This sounds clean but has drastic implications for business logic. Reports that used to be built with a single JOIN across multiple tables now require a reporting service with its own aggregated data model, updated via event sourcing or CDC from the source services. Consistency between services moves from being a database problem to being an architecture problem.

Anyone who is unwilling to accept this consequence but still runs Microservices on a shared database is building a distributed monolith — the worst of both worlds. We see this regularly in audits, and it is always a major refactoring project that could have been avoided upfront.

Distributed Transactions: Saga and Outbox

Distributed transactions across service boundaries are by far the most complex chapter in microservice practice. ACID does not work across network boundaries. Two patterns have established themselves, both solid, both demanding.

The Saga pattern decomposes a business transaction — such as "create order, collect payment, reserve inventory, trigger shipping" — into a chain of local transactions, each in its own service. If a step fails, the previous steps must be undone via compensating actions. Sagas can be orchestrated, with a central saga coordinator, or choreographed, where each service reacts to events from others. Both variants are challenging to test because failure cases and ordering problems in the event flow must be explicitly modeled.

The Outbox pattern solves a related problem: how do I reliably publish an event at exactly the moment the associated database transaction succeeds? The solution is an outbox table in the same database as the business data. The database write and the event write happen in a single transaction. A separate relay process reads new outbox entries and sends them to the message bus with an at-least-once guarantee. This makes idempotency on the consumer side mandatory — an aspect teams frequently underestimate until duplicates appear in production.

Observability Overhead

In a monolith, a good log file and a simple APM tool are often sufficient. In a microservice landscape you need distributed tracing — typically OpenTelemetry with a backend such as Jaeger, Tempo, or a managed SaaS solution like Datadog or Honeycomb. A single request traverses five, ten, or more services, and without traces, debugging latency issues is virtually impossible. Metrics per service must be aggregated, correlated, and visualized. Logs must be centrally collected, searchable, and linked to trace IDs.

Realistically, a solid observability stack for a 20-service landscape costs 30,000 to 120,000 euros per year in tooling licenses, plus between half and one full platform engineer position for operation and correlation. Anyone running Microservices without this investment is flying blind. A deeper framework comparison is in the cluster article Kubernetes for the Mid-Market.

Migrating from the Monolith — Strangler Fig in Practice

When the decision is made to migrate from a classically grown monolith to a Modular Monolith or selectively to Microservices, the Strangler Fig pattern is the most robust approach. The name comes from the strangler fig tree, which grows around a tree and replaces it piece by piece without the original tree falling all at once. The migration runs in five phases:

  1. Insert a reverse proxy. An API gateway or reverse proxy is placed in front of the existing monolith. All requests now flow through this proxy, which initially passes everything through transparently. This is the prerequisite for selective routing in later phases.
  2. Identify the Bounded Context. The first extracted part should be a clearly bounded Bounded Context — typically an area with its own data ownership, clear interfaces, and manageable size. No big bang, no core domain module.
  3. Build the new service in parallel. The new service implements the functionality of the extracted context, initially with its own database that is populated from the monolith via sync or CDC.
  4. Redirect traffic. The reverse proxy progressively redirects the associated routes to the new service — first shadow traffic for comparison, then canary releases at increasing percentages, then fully.
  5. Delete the old code. The corresponding code path in the monolith is removed once the new service is running stably. This step is often forgotten but is central to maintainability.

Every phase can be rolled back at any time. That is exactly what makes Strangler Fig superior to the big-bang rewrite, which in our consulting practice fails or massively exceeds budget in at least two-thirds of cases. More detail on this in the cluster Legacy Modernization.

Conway's Law — The Organizational Conflict

Mel Conway formulated the observation in 1968 that the architecture of a system mirrors the communication structure of the organization that builds it. Four decades later, the law is well supported by empirical evidence. For the monolith-vs-microservices question, it has a hard consequence: if the organization works in functional silos — a database department, a frontend department, a backend department — it will also build microservices along those interfaces. The result is technical services that distribute business logic across multiple teams. Every change to a business process then requires coordination across team boundaries — Microservices make the problem worse instead of solving it.

Successful microservice architectures follow a different organizational structure: cross-functional product teams that fully own a Bounded Context — frontend, backend, database, operations, product ownership. Anyone who wants to introduce Microservices technically without rethinking the organizational structure is systematically building distributed monoliths. The sequence is clear: restructure the organization along Bounded Contexts first, then consider whether Microservices are the right technical implementation.

Realistic Cost Comparison

The following table shows cost ranges from our consulting practice for a mid-market scenario: a product system with 20 developers, German hosting location, three environments, continuous operation. The figures are intended as realistic orientation, not as an offer.

Cost FactorModular MonolithMicroservices (10–20 services)
Hosting and infrastructure per year15,000–35,000 €60,000–150,000 €
Observability tooling per year3,000–8,000 €30,000–120,000 €
Platform engineering headcount share10–20% of one position1–2 full-time positions
Onboarding time for new developers1–2 weeks to productivity4–8 weeks to productivity
One-time migration costs50,000–200,000 €250,000–1,500,000 €
Deployment complexityOne artifact, standard pipeline10–20 pipelines, version matrix, compatibility tests

These figures do not mean that Microservices are fundamentally wrong. They mean the investment must be justified. In a company with 200 developers, multiple product lines, and clear scaling bottlenecks, the additional investment is a fraction of the speed gains achieved. In a company with 20 developers and a clear core product, it is wasted capacity.

Reepa Recommendation: Modular Monolith First

For roughly 80 percent of our mid-sized clients, the recommendation is: start with a cleanly structured Modular Monolith based on hexagonal architecture and Domain-Driven Design principles. Enforce module boundaries technically, not by convention. Keep database schemas logically separated per module — dedicated table prefixes or schemas within the same database — so that a later extraction remains possible. Invest in a clean test setup that makes Bounded Contexts independently testable.

This architecture typically holds for five to ten years, often longer. Only when concrete scaling or team topology reasons arise — and these must be named and measured, not anticipated — should a single Bounded Context be extracted into a standalone service via Strangler Fig. This targeted microservice extraction is a completely different operation from a big-bang migration and has a significantly higher success rate. For the technical interface question between services or modules, see our cluster on API Design REST vs GraphQL.

Frequently Asked Questions

At what team size do Microservices actually pay off?

In practice, Microservices pay off at around 50 active developers working in at least five to seven independent product teams. Below that threshold, coordination and infrastructure overhead almost always outweighs the benefits. Companies with fewer than 30 developers typically fare better with a Modular Monolith built on DDD principles — module-level decoupling is sufficient for most business requirements without incurring the operational overhead of distributed systems.

What is a Modular Monolith and how does it differ from a classic monolith?

A Modular Monolith is a single deployable artifact — like a classic monolith — but internally divided into strictly bounded modules that communicate only through defined interfaces. Unlike the classic monolith, which often ends up as an organically grown spaghetti structure, the Modular Monolith enforces boundaries via packages, namespaces, build-system constraints, or architecture linters. The result: the maintainability of a microservice system without the operational complexity of distributed calls and without distributed transactions.

How does the Strangler Fig pattern work during a migration?

The Strangler Fig pattern — named after the strangler fig tree — replaces a monolith incrementally by having a reverse proxy or API gateway progressively redirect routes to new services. The legacy system continues running until all functionality has been replaced. Advantages: no risky big-bang switchover, continuous business operations, rollback possible at any time. The prerequisite is a clearly bounded module in the existing codebase that is extracted first — typically a Bounded Context with its own data ownership.

How do you handle distributed transactions in a microservice architecture?

Classic ACID transactions across service boundaries are not practical in Microservices. Two patterns have established themselves: the Saga pattern, which decomposes a business transaction into a chain of local transactions with compensating steps, and the Outbox pattern, which atomically couples database writes and event publishing by first writing the event to an outbox table and then having a relay process push it to the message bus. Both patterns are robust but complex — one more argument in favor of the Modular Monolith for smaller teams.

How much more expensive is operating Microservices compared to a monolith?

For mid-sized companies with roughly 20 to 40 developers, the ongoing operational cost of a microservice architecture in our consulting practice runs two to three times higher than a comparable Modular Monolith — factoring in Kubernetes clusters, service mesh, observability stack, and additional DBA and platform engineer positions. On top of that come one-time migration costs of between 250,000 and 1.5 million euros. This investment only pays off when clear scaling or team topology reasons exist — not as a matter of fashion.

Ready to put your architecture to the test?

Let's talk for 30 minutes, no commitment. We assess your current codebase and team topology, give you an honest assessment of whether a Modular Monolith or selective microservice extraction is the right path, and deliver a realistic roadmap for the first 90 days — including migration risks and effort.

Schedule a 30-minute call
Mina Choi
Mina Choi · Full Stack Developer · Reepa Solutions

IT security and cloud architect with over ten years of experience. Advises mid-sized companies on architecture decisions between monolith, Modular Monolith, and Microservices, and accompanies legacy modernizations using the Strangler Fig approach.

Reviewed: May 22, 2026 · More about Mina

More from our Knowledge Hubs

🛡
Security
Cybersecurity
15 articles →
🧠
Artificial Intelligence
AI for the Mid-Market
15 articles →
Infrastructure
Cloud & DevOps
15 articles →
💻
Development
Software Development
15 articles →