Migrating a Monolith
The third case is moving an existing monolith onto Kubernetes incrementally, while it keeps serving production traffic. The interesting part is not the destination but the sequence: how to get from a running monolith to a Kubernetes-native system without a risky big-bang rewrite.
The pattern that works is the strangler fig — wrap the old system, route slices of functionality to new services one at a time, and let the monolith shrink. The traps are mostly about data and ordering.
Lift-and-Shift vs Strangler Fig
Two broad strategies. Lift-and-shift containerizes the monolith as-is and runs it on Kubernetes — fast, low-risk, but you gain little beyond consistent deployment until you decompose. The strangler fig incrementally extracts functionality into new services that take over slices of traffic, until the monolith is hollowed out. The pragmatic path combines them: lift-and-shift first to get onto the platform, then strangle from there.
Containerize First
Step one is getting the monolith into a container and onto Kubernetes unchanged — a Deployment, a Service, config externalized to ConfigMaps/Secrets, logs to stdout. This is unglamorous but it establishes the platform, the pipeline, and the routing layer you will extract through. Trying to decompose before the monolith even runs on Kubernetes adds two hard problems at once.
Routing and Incremental Extraction
With a routing layer in front (Ingress/Gateway, or a mesh), you can send specific paths or features to new services while everything else still hits the monolith. Extract one bounded capability at a time: stand up the new service, route its traffic to it, verify, and remove that code from the monolith. Observability is essential here — you need to see that the extracted path behaves before and after — which is why the migration depends on the monitoring and tracing from Chapter 9.
Data Is the Hard Part — Alternatives
The decomposition that breaks teams is the database. Splitting a shared monolithic schema into per-service data is far harder than splitting the code, and doing it first is the classic mistake — extract services that can share the existing database initially, and separate data later and carefully. What I'd do differently: resist premature microservices — extract only where there is a real seam and benefit, and stop when the remaining monolith is fine; a "modular monolith" on Kubernetes is a perfectly good end state. The alternative of a full rewrite was rejected outright: big-bang rewrites of working systems are the highest-risk path of all.
Lift-and-shift — containerize the monolith as-is — fast and low-risk, but little gained until you decompose.
Strangler fig — extract functionality incrementally behind a router until the monolith shrinks — the safe path to decomposition.
- Attempting a big-bang rewrite of a working monolith instead of incremental migration.
- Splitting the database first — data decomposition is the hardest part, not the starting point.
- Decomposing before the monolith even runs on Kubernetes, taking on two hard problems at once.
- Migrating without observability, so you can't tell whether extracted paths behave correctly.
- Over-extracting into microservices past the point of real benefit.
- Containerize and lift-and-shift first to establish the platform and routing layer.
- Use the strangler-fig pattern: extract one bounded capability at a time behind a router.
- Let extracted services share the existing database initially; separate data later and carefully.
- Lean on monitoring and tracing to verify each extracted path before and after.
- Stop when it makes sense — a modular monolith on Kubernetes is a valid end state.
Knowledge Check
What is the strangler-fig pattern for monolith migration?
- Incrementally extract functionality to new services behind a router until the monolith shrinks
- Rewrite the whole system from scratch at once on Kubernetes in one single big-bang cutover release
- Split the shared database into per-service schemas first, before touching any of the code
- Run the monolith completely unchanged forever and never extract a single service from it
What is the hardest part of decomposing a monolith, and when should it happen?
- Splitting the shared database — do it later and carefully, not first
- Containerizing the whole application image — do it dead last, after everything
- Writing the multi-stage Dockerfile — do it first, before anything else
- Choosing a Service type, ClusterIP or LoadBalancer — do it first
Why containerize and lift-and-shift the monolith before decomposing?
- It establishes the pipeline and routing layer you extract through, dodging two hard problems at once
- Kubernetes strictly requires a full microservices architecture before it will agree to run anything at all
- Containerizing automatically splits the shared database into clean per-service schemas for you
- It is the one and only supported way to run any monolithic application on Kubernetes at all
You got correct