HomeProjectsBlogContact

Monolith vs Microservices: Which Architecture Fits Your Project?

Microservices solve organisational and scaling problems, and introduce plenty of new ones. Why a well-structured monolith is usually the right start, and the signals that it's time to split.

Monolith vs Microservices: Which Architecture Fits Your Project?

Microservices became the default "serious" architecture in a lot of conference talks and job descriptions. Then many teams discovered that splitting a small app into a dozen services made everything slower to build and harder to debug. Both architectures have their place. The trick is knowing which problems each one actually solves.

The monolith

A monolith is one application, deployed as one unit, usually with one database. All features live in the same codebase and call each other directly.

Strengths:

  • Simple to develop: one repo, one build, one place to run locally.
  • Simple to deploy and operate: one thing to monitor, scale and roll back.
  • Fast internal calls: a function call instead of a network request.
  • Easy transactions: one database means data stays consistent naturally.
  • Easy refactoring: move code between modules with your editor's help.

Weaknesses (at larger scale):

  • Many teams working in one codebase can step on each other.
  • One slow test suite or long build affects everybody.
  • You scale everything together, even if only one part is busy.
  • A bad deploy of one feature can take down all of them.

Microservices

Microservices split the system into small, independently deployable services, each owning its own data and communicating over the network (HTTP, gRPC or messages).

Strengths:

  • Team autonomy: each team owns, deploys and scales its services independently.
  • Independent scaling of hot spots.
  • Fault isolation, if designed carefully.
  • Technology freedom per service, when genuinely useful.

Costs, which are easy to underestimate:

  • Distributed systems problems: network failures, timeouts, retries, partial failures.
  • Data consistency: no single transaction across services, so you need patterns like sagas and eventual consistency.
  • Operational overhead: many deployments, service discovery, centralised logging, distributed tracing, API versioning between services.
  • Harder debugging: one user request may cross five services. (Logging and monitoring.)
  • Slower local development: running the whole system on a laptop gets complicated.

Microservices solve people problems first

The biggest benefit of microservices is organisational: letting many teams work and deploy independently. If you have one team, or a handful of developers, you pay all the costs without getting that benefit.

The sensible default: a modular monolith

Start with a monolith, but organise it into clear modules with boundaries:

src/
  modules/
    billing/      # owns its tables, exposes a small interface
    catalog/
    orders/
    users/
  shared/
  • Each module owns its data and exposes a defined interface to others.
  • Modules don't reach into each other's internals or tables.
  • Dependencies between modules are explicit and kept to a minimum.

You get the simplicity of one deployable app with most of the structure of separate services. If you ever need to extract a service, a well-bounded module is easy to pull out. (Structuring projects for growth.)

Signals that it might be time to split

  • Several teams constantly block each other on releases.
  • One part of the system has very different scaling or reliability needs, like video processing, search indexing or a public API under heavy load.
  • A component needs a different runtime or language for a strong reason.
  • Build and test times hurt everyone despite optimisation.

Even then, extract one service at a time, starting with the clearest boundary, and keep the rest as a monolith. Background workers that process queues are often the easiest first extraction. (Background jobs.)

Anti-patterns to avoid

  • The distributed monolith: services that must be deployed together and call each other synchronously for every request. All of the costs, none of the benefits.
  • Shared database across services: couples them tightly again.
  • Splitting by technical layer ("the database service," "the validation service") instead of by business capability.
  • Microservices for a brand new product whose boundaries you don't understand yet. You'll draw the lines in the wrong places.

FAQ

Should I start with microservices?

Usually not. Start with a well-structured modular monolith, which is simpler to build and run, and extract services later when there's a clear organisational or scaling reason.

What is a modular monolith?

A single deployable application organised into well-defined modules with clear boundaries and owned data, combining monolithic simplicity with much of the structure of microservices.

Are monoliths outdated?

No. Many successful, large-scale products run on monoliths. The architecture should match team size, product maturity and real scaling needs, not trends.

Keep reading

More from the workbench

All articles →