Skip to content

Concept

Database per Service

Why each microservice should own its database — and what you give up when every service still shares one.

Once you break a monolith into microservices, data management becomes the next headache. Broadly you see two options:

  1. Database for each individual service
  2. Shared database

Database per service means each microservice has its own DB. Shared database is basically monolith-style: all microservices talk to the same database.

And honestly, shared database is not very useful. It’s not considered a successful approach. Let’s see why.

Shared database — what breaks

First problem: you cannot scale databases individually.

There’s no separate DB per service. So if one microservice is getting way more traffic and stressing the database, you can’t just scale the part that service uses. You scale the whole database server. The quieter services also “enjoy” those extra resources whether they need them or not. Not feasible.

Second problem: schema changes leak.

If one service runs a Liquibase (or any migration) and it fails, the DB server may not come up cleanly — and other services get hit too. Or you change a table from one service, another service was using that table, it has no clue what changed, and it starts failing. One service’s change affects the others.

The good part? Joins are fast. One database, so join queries are easy and you don’t pay extra network latency for them. That’s the main benefit people cling to.

Database per service — the rules

With database per service, a few conditions matter:

  1. No service is allowed to query another service’s database directly.
  2. A service can ask another service for data — through the API — but it cannot touch that DB.
  3. Each service can pick its own DB type. SQL here, NoSQL there, time-series somewhere else.

That third point is underrated. If a service only deals with timestamped trade-chart style data, a time-series DB can be faster and more efficient for that service alone. With a shared DB you’re locked into whatever you chose at the start. Migrate SQL → NoSQL and every service feels it.

Shared DB vs database per service
Shared database (problem)
everyone hits the same databaseSvc Awriting…Svc BcoupledSvc CcoupledOne shared DBhot pathcan't scale one service aloneschema change leaks

One DB — scale and schema changes couple every service

Joins are easy. Independence is gone.
Shared DB                         Database per service

[Svc A]─┐                         [Svc A]──► DB A
[Svc B]─┼──► one DB               [Svc B]──► DB B
[Svc C]─┘                         [Svc C]──► DB C
                                     │
                                     └── ask other Svc via API
                                         (never query their DB)

Why teams still prefer database per service

Scaling becomes sane. If microservice #3 suddenly spikes on reads or writes and its DB is near max capacity, you scale that database. Others stay as they are. Or you scale down a quiet one and save money.

Efficiency and latency for that service can improve.

But it raises two new problems:

  1. Joins across services are gone. You have to ask other services for data. If assembling that data is complex, latency and overhead go up — and your app can get slower instead of faster.
  2. Transactions that span multiple service databases. If one business operation updates service A, then B, then C, and something fails in the middle, data goes inconsistent. You need a way to handle that.

That’s where CQRS and Saga come in. CQRS helps with the join / heavy-read problem. Saga helps when a transaction spans multiple microservices.

When not to use this

Don’t force database-per-service on a three-person team with one product and light traffic. You’ll invent distributed problems before you have scale.

Shared DB (or even a modular monolith with clear table ownership) can be fine early — as long as you’re honest that it’s temporary and you don’t let every service write every table forever.

Production pitfall

“Just one quick join.” Someone opens a read replica of another service’s DB “only for reporting.” Six months later half the company depends on that backdoor. You’ve rebuilt shared database with worse ownership. If you need cross-service data, go through the API, a proper read model (CQRS), or an agreed analytics pipeline — not silent cross-DB queries.