DBRaven
Pattern · federation

Database Per Service

mature

Summary

Assign each service exclusive ownership of its own database schema or instance, prohibiting direct cross-service database access and enforcing data encapsulation at the service boundary.

Problem

Shared databases create coupling between services: schema changes cascade across service boundaries, slow queries from one service degrade others, and independent deployment and scaling become impossible when services share a data store.

Description

In a shared-database architecture, multiple services read and write the same tables. Schema changes in one service break others. A slow query from one service degrades database performance for all services. Operational incidents in one service can corrupt data owned by another. Data model coupling prevents services from being deployed or scaled independently.

Database-per-service enforces a hard boundary: each service owns a set of tables (or an entire schema or database instance) that no other service can access via SQL. The only way to read or modify another service's data is via that service's API. This enables independent schema evolution, independent scaling, independent operational failure domains, and independent technology selection (one service uses PostgreSQL, another uses Redis, another uses Cassandra).

The boundary is enforced at multiple levels. At the network level: database credentials are service-specific; no service has credentials for another service's database. At the schema level: tables are prefixed or namespaced per service; global database users do not have cross-service grants. At the process level: shared ORM models or shared schema migration tools are a code smell that signals boundary violation.

The fundamental operational consequence is that queries requiring data from multiple services cannot be expressed as SQL JOINs. They require one of: (1) API composition : the calling service fetches from each service's API and joins in memory; (2) event-driven denormalisation: downstream services subscribe to upstream events and maintain their own read-optimised copies of relevant data; (3) a dedicated reporting store that aggregates data from multiple services for analytical queries.

Cross-service ACID transactions are impossible without a distributed transaction protocol. The Saga pattern is the standard substitute, accepting eventual consistency at the business transaction level.

Tradeoffs

Service independence
+0.9

Complete schema, deployment, and scaling independence per service

Failure isolation
+0.8

Database failure in one service does not affect other services

Cross-service queries
-0.7

SQL JOINs are impossible; API composition or event denormalisation required

Distributed transactions
-0.6

Cross-service ACID is impossible without 2PC; Saga provides eventual consistency only

Operational complexity
-0.5

Multiple databases to provision, monitor, backup, and operate

Data consistency
-0.4

Eventual consistency via events; stale reads during propagation lag

When to use

Services are independently deployable and owned by separate teams

Independent deployment requires independent data schemas; a shared database forces coordinated deployments whenever a schema change is made

Services have different scaling requirements

A write-heavy service and a read-heavy service have different database scaling strategies; database-per-service allows each to scale independently

Service boundaries are well-defined with stable API contracts

Data ownership only works when it is clear which service owns which data; ill-defined boundaries result in ownership disputes and cross-service queries

Team can maintain Saga patterns or API composition for cross-service data

Eliminating cross-service SQL joins requires alternative integration patterns; team must be capable of implementing and operating these

When not to use

Services are small and owned by a single team without operational independence needs

For small systems, a single database with schema namespacing achieves most of the benefit with a fraction of the operational overhead

Reports and analytics require frequent ad-hoc joins across many service domains

Analytical queries joining across many service databases require either an integrated reporting database or an ETL pipeline; if this is the primary use case, sharing a database for analytics is pragmatic

Strong ACID transactions across service boundaries are required

Database-per-service makes cross-service ACID transactions impossible without 2PC; if the business domain requires them, the service boundaries are wrong

Operational Requirements

mandatory

Enforce database credential isolation: no service holds credentials for another service's DB

Without credential isolation, the boundary is advisory only; direct cross-service SQL queries will be written under deadline pressure

mandatory

Define data ownership boundaries in documentation before implementation

Unclear ownership produces ownership disputes and cross-boundary queries; define which service owns each domain entity before coding

recommended

Design and deploy an integrated reporting solution for cross-domain analytics

Ad-hoc analytics across many service databases requires a separate reporting store or data warehouse; plan this before the first cross-domain report is requested in production

mandatory

Version event schemas from day one for cross-service event integration

Services subscribed to each other's events will break if event schemas change without versioning; schema evolution must be planned upfront

Characteristics

Scales on
read
Implementation complexityhigh
Operational complexityhigh
Scaling ceilingCross-service data aggregation cost grows with the number of services and the complexity of the join. A report spanning 10 service APIs requires 10 API calls and in-memory assembly; latency is the sum of the slowest API response time, not a single query. Event-driven denormalisation keeps data eventually consistent and requires careful schema versioning as event formats evolve.

Technologies

Canonical

postgresqlmongodbredis

Alternatives

cassandradynamodbmysql

Relationships

Evolves from

strangler fig

Complements

saga patternoutbox patternevent sourcingstrangler fig

Conflicts with

two phase commit

Basis

Core microservices pattern with well-documented operational consequences; cross-service query and transaction challenges are the primary adoption blockers

Related Architecture Knowledge

Inbound: affects this entity

ComplementsPattern
event sourcing
Grounded

Event sourcing and database-per-service reinforce each other: each service owns its event log and materializes its own read models independently, with cross-service data sharing happening via published events rather than shared database access.

Tradeoffs

  • ·Cross-service queries require eventual consistency: no joins across service event logs
  • ·Event schema versioning is a distributed coordination problem: schema changes require coordinated deployment
  • ·Debugging cross-service workflows requires distributed tracing (correlation IDs across event boundaries)
Full relationship →
Evolves IntoPattern
strangler fig
Grounded

Strangler Fig migration progressively extracts services from a monolith; each extracted service is the natural point at which a dedicated database is introduced, evolving the shared monolith database toward a database-per-service topology as the migration progresses.

Tradeoffs

  • ·Dual-write migration window is operationally complex: must reconcile divergence before final cutover
  • ·Database extraction is the hardest part of strangler fig: shared tables with join dependencies require careful ordering
  • ·Each extracted service needs its own connection pool, backup, and monitoring: operational complexity grows linearly
Full relationship →