Stackbook Logo
data-stateestablished · high operational burden

Database per Service

Also known as: service-owned-data, private-datastore

Intent

Give each microservice exclusive ownership of its data so services can evolve and scale independently.

Problem

A shared database couples services through its schema, so one team table change can break another and deployments must be coordinated. Contention and noisy neighbors affect unrelated features. Independence of services is illusory if they share storage.

Forces

  • •Teams need to change schemas without cross-team coordination
  • •Different services have different storage needs
  • •Business operations that span services need consistency
  • •Reporting wants a combined view of data

Solution

Overview

Database per service enforces the boundary at the storage layer. If another team can query your tables, your schema is a public API whether you meant it or not.

How it works

Services share data only through contracts.

Order Service   --> orders_db
Payment Service --> payments_db
Customer Service-> customers_db

Order needs customer name:
  option A: call Customer API (runtime coupling)
  option B: subscribe to CustomerUpdated events,
            keep a local read copy (autonomy, eventual)

Logical separation can be enough at first: separate schemas with separate credentials in one cluster, split into clusters when scale demands.

Data needed by several services follows one of a few patterns. API composition has a gateway call several services and merge results. A local read model keeps a copy of the other service data, updated from events with an outbox for reliable publishing. A shared reference dataset, like country codes, can be replicated as a library or read-only table. Choose per case by how fresh the data must be and how bad it is when the owning service is down.

Pitfalls

  • Sharing one database with per-team tables and calling it microservices.
  • Chatty synchronous calls to fetch data, creating a distributed monolith.
  • Trying to emulate joins in application code on hot paths.
  • Splitting too early before boundaries are understood.

Key takeaways

  • Own your data; expose it through APIs or events only.
  • Use sagas and events instead of distributed transactions.
  • Replicate needed data locally and accept eventual consistency.
  • Start with logical separation and split physically when needed.

✓ When to Use

  • •Microservice architectures with independent teams and release cycles
  • •Services with distinct scaling or storage requirements
  • •Domains with clear bounded contexts

✗ When Not to Use

  • •Small teams and modular monoliths where one database is simpler
  • •Domains requiring frequent strong-consistency joins across entities
  • •Early products where service boundaries are still unclear

Pros

  • +Loose coupling and independent deployments
  • +Right-sized storage and scaling per service
  • +Failures and load are isolated

Cons

  • −No cross-service joins or ACID transactions
  • −Data duplication and eventual consistency
  • −More databases to operate

Cost Profile

Infrastructure

High - more database instances

Operational

High - backups, upgrades and monitoring per store

Cognitive

High - sagas, duplicated data and consistency

Failure Modes

  • Teams bypass the API and read another service tables, recreating coupling

  • Saga failures leave data inconsistent without compensation

  • Reporting queries hit service databases directly and hurt production

Real-World Examples

Alternatives

    Related Patterns

    • saga-pattern
    • cdc
    • outbox-pattern
    • polyglot-persistence

    Competency Domains

    distribution communicationdata state