When teams first start building microservices, a common question appears:
“Why not just share one big database between all the services?”
It sounds simpler — one schema, one connection, less setup.
But in practice, sharing a single database is one of the fastest ways to lose the main benefit of microservices: independence.
Let's explore why the “one database per service” rule exists and how it works in real systems.
The Problem With a Shared Database
Suppose you have two services:
- Users Service – handles user profiles
- Orders Service – tracks purchases
Both share one database, company_db
, and both read and write to the same users
table.
It feels convenient at first — until one team adds a column or updates a constraint and suddenly the other service breaks.
A single migration or heavy query can take down everything.
Instead of autonomy, you’ve built a distributed monolith: separate codebases tied together by one fragile database.
The Principle of Autonomy
The idea behind “one database per service” is simple: each service owns its own data.
That means:
- Its schema belongs only to that service.
- It can change and deploy independently.
- Other services can’t reach into its tables.
Each service stores exactly what it needs and exposes that data through an API or event rather than a shared table.
Sharing Data the Right Way
1. Through APIs
Services can communicate directly over HTTP (REST or gRPC).
$response = $httpClient->request('GET', 'https://users-service/api/users/42');
$user = $response->toArray();
This keeps ownership clear — the Users service remains the single source of truth.
2. Through Events
When data changes, services publish an event (e.g. UserCreated
), and other services subscribe:
- The Users service emits
UserCreated
- The Orders service listens and stores a small copy of the user data locally
This is event-driven architecture, and it supports scalability and resilience.
Each service updates itself asynchronously without waiting on others.
Duplication Isn’t a Mistake
Some data will be duplicated across databases — and that’s okay.
It’s called eventual consistency: systems trade instant synchronization for autonomy.
Each service keeps only what it needs.
If the master data changes, it will sync via events shortly after.
Duplication is cheaper than dependency.
Example in PHP
Users Service (MySQL)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(180) UNIQUE
);
Orders Service (PostgreSQL)
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INT,
total DECIMAL(10,2)
);
The Orders service never connects to the Users database.
It either calls the Users API or listens to a UserCreated
event.
Benefits at a Glance
- Independence — Services deploy and evolve separately.
- Scalability — Each database scales to its own load.
- Fault Isolation — One DB crash doesn’t break others.
- Security — Services only access their own data.
- Technology Freedom — Mix MySQL, Postgres, MongoDB, Redis, etc.
Trade-Offs
- Data duplication — intentional for autonomy
- Eventual consistency — updates are asynchronous
- More operational overhead — multiple databases to manage
But for growing systems, these trade-offs are well worth the independence gained.
The Big Picture
Having one database per service means more than database configuration.
It’s a mindset: every microservice should be self-contained, responsible for its own data, and replaceable without coordination.
That’s how teams build scalable, reliable, and evolvable systems.
Further Reading
- Microservices.io – Database per Service: https://microservices.io/patterns/data/database-per-service.html
- Martin Fowler – Microservices: https://martinfowler.com/articles/microservices.html
- 12-Factor App Principles: https://12factor.net/
- Symfony Messenger for Event-Driven PHP: https://symfony.com/doc/current/messenger.html
Top comments (0)