Skip to content
ansezz.
← Back to blog
Architecture Feb 22, 2026 7 min read 1,376 words

Monolith to microservices: a pragmatic guide

Skip the big-bang rewrite. The strangler fig pattern, anti-corruption layers, and Docker-first steps to move from monolith to microservices safely.

Anass Ez-zouaine

Backend · Architect · AI

▸ Share

Pop-art illustration of a monolith being gradually replaced by smaller services
▸ On this page (6)

A big-bang rewrite can kill the business while the engineers play with new toys. Strangle the monolith one route at a time instead.

Your monolith is a ticking time bomb, and every feature you add brings the explosion closer.

I have seen it happen a dozen times. A startup begins with a clean Laravel or Rails app. It is fast, easy and productive. Then the team grows and the code base swells.

When it starts to hurt

Suddenly, a simple change to the checkout logic breaks the authentication system. Deployments that used to take five minutes now take forty.

You are no longer scaling your business. You are managing technical debt.

The distributed monolith trap

This is when most developers start dreaming of microservices: every service isolated, every deployment instant. The reality is often a nightmare.

Do it wrong and you end up with a distributed monolith. You get all the complexity of networking with none of the benefits of isolation.

Pragmatic scaling

I skip the “big bang” rewrite and use the strangler fig pattern to move from monoliths to microservices without losing my mind or my job.

If you are still deciding whether to split at all, start with monolith vs microservices. This post assumes you have made that call and want the migration playbook.

The problem with the big bang

When a monolith gets too heavy, the first reaction is to scrap it. I have seen companies spend two years on a rewrite only to ship a product with half the features of the original.

Coupling is the enemy

The monolith is a phase. The real problem is coupling.

When every part of your app knows too much about every other part, you cannot move. If you jump straight into microservices, you will likely port those dependencies into a network layer. Instead of a function call failing, you get a 500 error across a network socket.

Extract what hurts most

I prefer a slower, deliberate approach focused on high-value extractions. Look for the parts of the app that hurt the most.

Is image processing slowing down the web server? Is the reporting engine locking up the database? Those are your first candidates for microservices.

The strangler fig pattern in practice

Martin Fowler named this approach after a tree that grows around another tree. It starts as a small vine and eventually replaces the host entirely.

In software, you build new features as services while the old monolith keeps running.

Put a router in front

The process starts with an API gateway or a load balancer. I put a routing layer in front: Nginx or a Google Cloud HTTP(S) load balancer with Cloud Armor added for WAF and DDoS protection.

If a request comes in for /api/v1/orders, the URL map sends it to the new service. Everything else goes to the old monolith. (If you’re unsure which box does what here, see load balancer vs API gateway.)

Flip back if it fails

This lets me test the new service in production with real traffic while the monolith acts as a safety net. If the new service fails, I flip the routing back.

I don’t have to migrate everything at once. I can migrate one endpoint at a time.

Move one route, watch it under real traffic, and keep the old path one switch away.
Comic panel of a robot pulling a rail switch lever beside a vine-covered stone tower as a train heads toward a modern glass building
Move traffic one route at a time from the old system to the new one.

Big-bang rewrite

Freeze features, rebuild everything for months or years, then switch over in one risky launch.

Strangler fig

Route one endpoint to a new service, prove it with real traffic, then move the next. The monolith shrinks while the business keeps shipping.

Containerization with Docker

You cannot do microservices without Docker. I treat every service as a black box.

The monolith might run on an old version of PHP while the new service is a lean Go binary or a modern Laravel instance. Docker makes that possible.

Containerize the monolith first

I start by containerizing the monolith. Even if it stays a monolith for another year, the container forces me to define its environment and makes the infrastructure reproducible.

# a simplified example of a service container
FROM php:8.4-fpm

WORKDIR /app
COPY . /app

RUN apt-get update && apt-get install -y \
    libpq-dev \
    && docker-php-ext-install pdo_pgsql

EXPOSE 9000
CMD ["php-fpm"]

Scale each service on its own

Once the monolith is containerized, I can deploy it to a platform like Google Kubernetes Engine (GKE).

This is where microservices pay off. I can scale the order service to fifty instances during a sale while keeping the blog service at two.

Communication and the anti-corruption layer

The hardest part of microservices is the data, not the code. Your monolith has a single database, and your microservices should each have their own. So how do they talk?

Don’t reach into the old database

I use an anti-corruption layer (ACL). When I extract a service, I don’t let it reach back into the monolith’s database. That would be cheating.

Instead, I create an interface. If the new service needs user data, it asks the monolith through a private API or a message queue like Google Pub/Sub.

Keep the new service clean

The new service doesn’t care about the legacy app’s messy database schema. It only cares about the data it gets through the ACL.

When the user logic is migrated later, I update the ACL to point to the new user service. For the asynchronous side (letting services react to events instead of calling each other directly), I lean on event-driven Pub/Sub or a RabbitMQ-backed queue.

Comic panel of a human clerk handing a package through a service window to a smiling robot beside a boarded-up door
New services ask the old system for data through a clean interface.

Cloud infrastructure and DevOps

Scaling a monolith usually means buying a bigger server. Scaling microservices means managing a fleet of small instances, so I rely on cloud-native tools to manage the complexity.

Infrastructure as code

I use Terraform to manage my infrastructure as code. That keeps staging and production identical.

If I need a new database for a service, I define it in code instead of clicking around a dashboard.

One pipeline per service

For deployments I use tools like GitHub Actions or Coolify. Every service has its own pipeline.

If I update the checkout service, I only deploy the checkout service, without worrying about the rest of the system.

The hidden costs of microservices

I’d be lying if I said this was all sunshine and rainbows. Microservices come with a “complexity tax”: distributed logging, service discovery and eventual consistency.

Only split when it hurts

My advice is to move to microservices only when the pain of the monolith is greater than the complexity tax. If your team is three people and your app is simple, stay in the monolith. You will move faster.

If you are hitting walls every day and your developers are afraid to touch the code, it is time to start strangling.

Key takeaways

  • Start with an API gateway to handle routing.
  • Containerize your monolith first to normalize the environment.
  • Use the strangler fig pattern to migrate one domain at a time.
  • Build an anti-corruption layer to keep new services clean.
  • Invest in infrastructure as code early on.
  • Only split when the monolith starts to hurt your productivity.

Migration takes time. I have spent months on a single extraction to get it right, because the goal is a system that grows with your business, not a count of services. If you’re planning that first extraction, here’s how I help teams move from a monolith to services without a rewrite, or tell me about your migration.

Have you ever tried a “big bang” rewrite only to regret it six months later?

▸ Made it to the end? Send it around.

▸ Share

▸ Comments