Database per Service
Database per Service assigns each service private data storage that other services access only through published contracts.
- Private storeOnly the responsible service reads and writes directly.
- Integration contractAPI or event replaces foreign table access.
- Distributed consistencyMakes delay, saga, and projection visible.
Context
Why this is important
The pattern protects write ownership and independent schema evolution; it moves shared joins and atomic multi-service changes into integration patterns.
The distributed extension in the shop scenario is hypothetical; the current shop remains a modular monolith with seven modules and one shared database.
Database per Service: decision boundaries
The current shop remains a modular monolith with seven modules and one shared database; each module owns its tables. A hypothetical service split gives Payment private storage and removes all table access from Order. Order status receives payment information through a versioned contract and projection. The team migrates incrementally, tests permissions, duplicate events, and projection rebuild, and adopts the split only when the quality benefit justifies distributed cost.
This is how you read the picture
- Private store Permissions enforce boundary
- Integration contract Versioned access
- Distributed consistency Explicit status
| Comparison | Aspect | Sound use | Limit |
|---|---|---|---|
| Separate schemas | Clear rights on shared server | Incremental separation | Shared failure and resources |
| Own database | Independent operation and schema | Strong technical boundary | More migration, backup, and observability |
| Shared database | Simple joins and transactions | Deliberate shared infrastructure | Schema and load coupling |
Benefits & limitations
Helps if:
- Incremental separation
- Strong technical boundary
- Deliberate shared infrastructure
Boundaries
- Shared failure and resources
- More migration, backup, and observability
- Schema and load coupling
In practice
- Inventory every direct table access across modules and assign the read or written fields to a business owner. Replace one foreign write access with an explicit module contract first.
- Remove Order’s direct access to payment data in a test environment and produce the same order view through an API or projection. Test failure state, freshness, and rebuild.
- Compare separate schemas, a dedicated database, and a shared database by change autonomy, failure radius, transactions, backup, and operational cost. Document the evidenced quality objective.
Read the detailed explanation
Private means a boundary enforced by permissions and ownership; separate schemas on one server can suffice when foreign direct access is impossible.
Other services read through APIs, events, or projections. Flows across stores need sagas, idempotency, and explicit consistency rather than a shared database join.
Data Ownership determines the business owner. Shared Database is a deliberate alternative with shared operational and schema impact.
Check your understanding
Test yourself in three stages
ReadingCheck in the picture
What is the core task of Database per Service?
View the solution with justification
Database per Service assigns each service private data storage that other services access only through published contracts.
ApplyingTransferred to a new situation
Which assumption is hypothetical in the shop?
View the solution with justification
A hypothetical service split gives Payment private storage and removes all table access from Order. Order status receives payment information through a versioned contract and projection.
EvaluateWeighing an alternative
Which three points require evidence before adoption?
View the solution with justification
Private store, Integration contract, Distributed consistency.
Explore further
These building blocks continue the thoughts of this page.