The microservices fashion peaked in 2018 and quietly cooled. By 2026 the consensus is: most products start as a modular monolith and split when they have specific reasons to. This post is the pragmatic guide.

Why monolith first

  • Faster to build. One deploy, one DB, one repo.
  • Simpler to debug. Stack traces don’t span network.
  • Easier to refactor. Move code freely.
  • Cheaper to operate. One process, fewer moving parts.

For a team of 1–10 engineers shipping a product, monolith wins almost always.

Modular monolith — the right starting shape

app/
├── modules/
│   ├── orders/
│   │   ├── api/         # routes
│   │   ├── service/     # business logic
│   │   ├── repo/        # DB access
│   │   └── domain/      # types
│   ├── billing/
│   ├── inventory/
│   └── notifications/
├── shared/             # only what truly cross-cuts
└── main.py

Rules:

  • Modules talk via well-defined interfaces, not raw DB access.
  • One module’s data is opaque to others — request via service.
  • No cross-module DB joins.
  • Shared code is minimal.

Result: each module has the boundary of a microservice but lives in one process. Splitting later is a refactor, not a rewrite.

When to split

Real reasons to split a monolith:

  1. Team independence. Different teams own different services; deploy independence matters.
  2. Resource asymmetry. ML inference needs GPUs; the rest doesn’t. Split to scale appropriately.
  3. Different runtime needs. One module is Rust for perf; rest is Python.
  4. Compliance. A subset of code touches PCI / HIPAA data; isolate to limit scope.
  5. Real scale. One module’s load profile diverges from the rest.

Bad reasons:

  • “We’re growing.” Monolith scales further than people think.
  • “We saw a talk about microservices.”
  • “Resume-driven development.”

The cost of microservices

Real cost:

A 5-service monolith → 5 microservices is a 5× operational burden, often without commensurate benefit.

How to split well

When the moment comes:

  1. Pick the boundary. A module that’s already cleanly separated.
  2. Establish the contract. API spec; tests against it.
  3. Run both for a phase — same code, deployed monolith and as a service.
  4. Cut traffic over to the service.
  5. Remove the module from the monolith.

The modular monolith made this incremental.

Read this next

If you want a modular-monolith template (FastAPI / Hono / Axum flavors), it’s at rajpoot.dev .


Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .