Skip to main content

Shared Database Across Services

Multiple services accessing one shared database, creating tight coupling.

TL;DR

Multiple services sharing one database creates tight coupling that defeats microservice independence. Schema changes affect all services. One service's writes corrupt another's data. Can't scale independently—scaling requires scaling entire database. Services become interdependent on the database level, losing autonomy. Solution: database-per-service pattern where each service owns its data and communicates through APIs, not shared tables.

Learning Objectives

You will be able to:

  • Understand why shared databases break service independence
  • Design database boundaries aligned with service boundaries
  • Implement asynchronous data synchronization
  • Handle distributed transactions safely
  • Migrate from shared to independent databases
  • Evaluate when shared databases are appropriate (rarely)

Motivating Scenario

You have User Service, Order Service, and Payment Service sharing one PostgreSQL database. This seems efficient:

  • Single database to manage
  • Easy to query across services
  • ACID transactions across services

But problems arise:

Problem 1: Schema Coupling Order Service adds a discount_code column to Orders table. But Payment Service has triggers on that table. The migration breaks Payment Service for 10 minutes during deployment.

Problem 2: Independent Scaling User Service gets heavy traffic (reading user profiles). You need to scale database horizontally. But the shared database must scale for all services. Now you're scaling Payment Service's database (which has light traffic) just to handle User Service load.

Problem 3: Implicit Dependencies Order Service directly queries Payments table. Payment Service doesn't know Order Service depends on it. Changes to the schema are risky.

Problem 4: Data Corruption Payment Service bug writes bad data to Payments table. Order Service reads corrupt data and creates bad orders. Now you have data consistency problems spanning services.

You realize: this isn't microservices, it's distributed application tightly coupled through the database.

Core Explanation

Why Shared Databases Look Good

  • Simple: one database, ACID transactions, joins work
  • Efficient: no network calls, direct queries
  • Familiar: traditional monolith pattern

Why Shared Databases Break

  1. Tight Coupling: Services are coupled through schema
  2. Scaling Limitations: Can't scale services independently
  3. Deployment Risk: Schema changes affect multiple services
  4. Data Ownership Ambiguity: Who owns what data?
  5. Blame Shifting: "Payment Service broke my data"

The Database-Per-Service Pattern

Each service owns its data store. Services communicate through APIs:

User Service (owns: users) ← API → Order Service (owns: orders)
Order Service ← API → Payment Service (owns: payments)

Changes to Order schema don't affect Payment Service.

Code Examples

-- Single database shared by User, Order, Payment services
-- ALL services can read/write ALL tables

CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR,
email VARCHAR
);

CREATE TABLE orders (
id INT PRIMARY KEY,
user_id INT REFERENCES users(id),
total DECIMAL
);

CREATE TABLE payments (
id INT PRIMARY KEY,
order_id INT REFERENCES orders(id), -- Coupling!
amount DECIMAL,
status VARCHAR
);

-- User Service directly queries all tables
SELECT * FROM orders WHERE user_id = ?;
SELECT * FROM payments WHERE order_id = ?;

-- Payment Service directly queries all tables
SELECT * FROM orders WHERE id = ?;
UPDATE orders SET status = 'paid' WHERE id = ?; -- Modifying Order's data!

-- Order Service modifies Payment table
INSERT INTO payments VALUES (...);

-- All services are tightly coupled through the database
-- Problems:
// 1. Payment Service modifies orders (who owns orders?)
// 2. Schema change in payments affects all services
// 3. Can't scale database independently per service
// 4. No data isolation

Design Review Checklist

  • Does each service have its own database?
  • Are there any cross-service foreign keys?
  • Do services communicate through APIs, not shared tables?
  • Can you deploy one service without coordinating database changes?
  • Can you scale one service's database independently?
  • Is data ownership clear (no ambiguity)?
  • Are there no direct cross-database queries?
  • Do services use event-driven communication for consistency?
  • Can you change a service's schema without affecting others?

Showcase

Signals of Shared Database Coupling

  • Multiple services share one database
  • Cross-service foreign keys
  • Service A queries Service B's tables
  • Schema change requires coordinating multiple services
  • Can't scale services independently
  • Database per service
  • No cross-service foreign keys
  • Services communicate via APIs
  • Schema changes isolated
  • Independent scaling possible

One Takeaway

info

Database-per-service eliminates the most insidious coupling: the database schema. Services become truly independent when they don't share data stores.

References

  1. Database per Service Pattern ↗️
  2. Microservices Architecture ↗️
  3. Event Sourcing & CQRS ↗️
  4. Saga Pattern for Distributed Transactions ↗️