Database per Service
Table of Contents
This page defines the service architecture pattern Database per Service in the pattern language. Each service owns its data, and other services reach it only through the owner's operations. In ORE Studio components share one PostgreSQL instance, and still no service reads or writes another component's tables.
1. Also known as
- Private data per service.
2. Context
Services are deployed separately and owned separately. The deployment happens to put their tables in one database.
3. Problem
Where does a service's data live, and how does another service read it?
4. Forces
- A direct read is one query and no round trip.
- A direct read skips the owner's authorisation and couples two schemas.
- Owners must be free to change their tables.
- Some reads span owners.
5. Solution
Each service owns its tables and serves them through operations on the bus. Any other service reads and writes them only through those operations, with the identity the call needs, and RLS applies as for any caller. A read that spans owners calls each owner, or a composer calls them and joins the answers.
Figure 1: Database per Service: ORE reads refdata's and analytics' documents through their operations, never their tables.
Source: [[./pattern_database_per_service.puml][pattern_database_per_service.puml]]. Regenerate with
plantuml -tpng doc/knowledge/service_architecture_patterns/pattern_database_per_service.puml.
6. Failure handling
| Concern | What the pattern does |
|---|---|
| Errors | An owner's refusal reaches the caller as an error, not as missing rows. |
| Timeouts | Each owner call has its own timeout. |
| Retries | Reads are safe to retry. |
| Idempotency | Writes across owners need a Saga. |
| Observability | Each owner logs the read it served. |
7. Pitfalls
- A shortcut through a shared connection. It compiles and returns rows, with no authorisation and no contract.
- An owner linked as a library. Linking another component's core library is the same shortcut in code.
- Many small calls. A per-row read across owners is slow; owners offer bulk reads.
8. Security
The owner's handler authorises every read, and RLS applies with the caller's tenant and party. A direct read would bypass both.
9. Resulting context
- Benefits
- Owners change their tables freely, and access control applies everywhere.
- Liabilities
- Round trips, and cross-owner reads need composition.
10. In ORE Studio
The curve construction, Bootstrapping a curve: from quotes to a published set, crosses refdata's recipe and market data's observations, each in its own store.
The surface construction, Constructing a volatility surface: from quotes to a published set, crosses refdata's recipe and conventions and market data's observations in the same way.
The market data path, a public fixing, a curve and a report, crosses four stores: market data, refdata, inbox and reporting, and each component owns its own.
- No service reads or writes another component's tables — the rule as a memory.
- Service-to-service auth — the reasons a service must not reach into another's repository.
- Transporting a package
- Data exchange journeys — the journeys that expose the boundary: a move across owners has no single transaction. — one bundle per owner, and a coordinator that reads only the manifest and never another owner's rows.
11. Related patterns
- Request-Reply — how the owner is asked.
- Saga — writes across owners.
- Cache-Aside — a reader's copy that the owner still owns.
12. Sources
- Chris Richardson, Pattern: Database per service, microservices.io.
- Sam Newman, Building Microservices, second edition, O'Reilly, 2021 — the case against sharing a database between services.
13. See also
- Service architecture patterns — the structure note that orders this pattern language, and where to read this page in it.