Skip to content

Database per Service vs Shared Database

1. Decision

Choose Database-per-Service as the mandatory golden rule for microservice architectures to guarantee loose coupling, independent domain scaling, schema change autonomy, and fault isolation; choose a Shared Database for monolithic architectures, early-stage MVPs, or tightly coupled legacy applications where single-database ACID transactions dominate.


2. 30-Second Answer

The database pattern fundamentally defines microservice independence. Database-per-Service mandates that every microservice owns and encapsulates its private database (or private database schema/keyspace). No outside microservice may query or write to another service's database directly—all data access must pass through published service APIs or event streams. This guarantees loose coupling, independent schema migrations, and technology freedom (polyglot persistence), but trades off single-database ACID joins for eventual consistency (Saga pattern). A Shared Database allows multiple microservices to read/write to common relational tables. While it enables easy cross-table SQL joins and local ACID transactions, it creates tight schema coupling, deployment locks, and shared database performance bottlenecks, forming a Distributed Monolith.


3. Decision Matrix

Option Best For Avoid When Latency Scalability Consistency Operational Complexity
Database-per-Service Microservice architectures, independent team autonomy, polyglot storage, high-scale cloud platforms Monolithic applications, small engineering teams (<10 devs), systems requiring strict cross-domain ACID joins Low local DB access; Async eventual cross-service lag Extremely High (Scales individual DB instances independently per service) Eventual Consistency (Saga / CDC) High (Data synchronization, Sagas, CDC pipelines)
Shared Database Monolithic applications, early-stage MVPs, small teams, reporting-heavy applications Autonomous microservice teams (creates deployment locks and schema change breaking risks) Sub-millisecond (Local relational SQL joins across domain tables) Bounded by single primary DB CPU/RAM/Disk limits Immediate ACID Low

4. Selection Rules

Requirement Best Choice Rationale / Example
Autonomous Microservice Deployments Database-per-Service Payment team alters table schema without breaking Inventory team's database
Polyglot Persistence (Best Tool for the Job) Database-per-Service User service uses PostgreSQL, Search service uses OpenSearch, Recommendation uses Neo4j
Early-Stage MVP Startup (<10 Engineers) Shared Database Single monolithic PostgreSQL DB enables rapid feature changes without sync pipelines
Prevent Microservice Cascading DB Crashes Database-per-Service A query surge on Analytics database does not starve core Order processing database
Cross-Domain Entity Aggregation Database-per-Service + CQRS Aggregate data via CDC events into a denormalized Read Model database

5. Tradeoffs

  1. Service Autonomy vs Cross-Domain Data Joins
  2. Gain (DB-per-Service): Services deploy independently without coordinating schema DDL locks.
  3. Lose (DB-per-Service): Cannot execute SQL JOIN across microservice tables; must aggregate in application layer or CQRS.
  4. Polyglot Persistence vs Operational Management Overhead
  5. Gain (DB-per-Service): Match storage engines to domain access patterns (Relational, Document, Graph, Cache).
  6. Lose (DB-per-Service): Managing backups, monitoring, and security for 10+ distinct database clusters.
  7. Single-Node ACID Transactions vs Distributed Saga Patterns
  8. Gain (Shared DB): Atomic multi-table updates (BEGIN ... COMMIT) within 1 database engine.
  9. Lose (Shared DB): Tight schema coupling creates a "Distributed Monolith" anti-pattern.
  10. Fault Isolation vs Eventual Consistency Synchronization
  11. Gain (DB-per-Service): Database outage on 1 service does not crash other microservices.
  12. Lose (DB-per-Service): Must run Change Data Capture (Debezium + Kafka) to sync data asynchronously.
  13. Data Ownership Clarity
  14. Gain (DB-per-Service): Single microservice team owns 100% of data lifecycle and access rules.
  15. Lose (Shared DB): Unclear data ownership when 5 services modify the same users table directly.

6. Interview Counter Questions

  1. Why is accessing another microservice's database directly considered the worst microservice anti-pattern?
  2. How do you handle cross-service SQL JOIN operations in a Database-per-Service architecture?
  3. What is a Distributed Monolith and how does a Shared Database contribute to it?
  4. How do you execute multi-service transactions without a Shared Database (Saga Pattern)?
  5. Does Database-per-Service require running separate physical database servers for every microservice?
  6. How does Change Data Capture (CDC via Debezium) maintain data consistency across Database-per-Service stores?
  7. What is Polyglot Persistence and what are its benefits and operational risks?
  8. How do you handle foreign key constraints across microservices in Database-per-Service?
  9. When is using a Shared Database acceptable in software architecture?
  10. How do you migrate from a Shared Database monolith to Database-per-Service using the Strangler Fig pattern?

7. Gold Standard Answers

  1. Querying another service's DB directly creates tight coupling. Schema changes in Service A silently break Service B's raw SQL queries, ruining deployment independence and violating encapsulation.
  2. Alternatives: (1) API Aggregation: Service A queries Service B API for missing fields over gRPC, (2) CQRS: Sync events via Kafka to build a pre-joined denormalized Read Model, (3) Data Replication: Replicate reference data asynchronously.
  3. A Distributed Monolith occurs when services are physically deployed separately, but tightly coupled via shared databases or synchronous call chains, combining distributed network latency with release dependency locks.
  4. Use the Saga Pattern: Replace a single 2PC ACID transaction with a chain of local ACID transactions in each service's private DB, emitting events to trigger the next step or compensating transactions on failure.
  5. No! "Logical Database-per-Service" assigns dedicated isolated schemas, logical databases, or user permissions inside a single database instance during early stages, enforcing API isolation without hardware waste.
  6. Debezium reads raw WAL logs of Service A's private DB, publishes change events to Kafka, and Service B's consumer worker writes updates to Service B's private DB asynchronously.
  7. Polyglot Persistence matches storage engines to domain access patterns (e.g. Postgres for Orders, Redis for Sessions, Neo4j for Fraud). Risk: Operational complexity managing different DB engines.
  8. Replace SQL Foreign Keys with logical application-level identifiers (e.g. store user_id integer in Order DB). Validate existence via API calls or asynchronous reference table replication.
  9. Acceptable in monolithic architectures, early-stage startups/MVPs, small teams (<15 devs) where domain boundaries are rapidly shifting, or read-only analytical reporting warehouses.
  10. Strangler Fig: Keep shared DB initially \(\rightarrow\) Create private DB for new microservice \(\rightarrow\) Sync historical data \(\rightarrow\) Dual-write via CDC \(\rightarrow\) Switch service reads to private DB \(\rightarrow\) Remove old tables from shared DB.

8. Common Mistakes

  • Connecting Microservice B directly to Microservice A's database to run a quick SQL JOIN or read.
  • Running separate physical database instances for 30 tiny microservices with 5 requests/min, wasting compute costs.
  • Maintaining foreign key constraints in code that cross microservice database boundaries.
  • Splitting application code into microservices while keeping 1 shared central database instance (creating a Distributed Monolith).
  • Expecting real-time strong consistency across isolated microservice databases without handling eventual consistency.

9. Keywords

Database-per-Service, Shared Database, Distributed Monolith, Encapsulation, Schema Migration, Polyglot Persistence, Cross-Service JOIN, Debezium CDC, Logical Database Isolation, Saga Pattern, Strangler Fig Pattern, API Aggregation.


10. Cheat Sheet

  • Golden Rule of Microservices: Database-per-Service! Microservice B MUST NEVER query Microservice A's database directly.
  • Data Access Rule: All cross-domain data access MUST pass through published APIs (gRPC/REST) or Event Streams (Kafka).
  • Shared DB Anti-Pattern: Shared databases form a Distributed Monolith (tight coupling, broken deployment autonomy).
  • Physical vs Logical: Can start with Logical Isolation (private schema/tables in 1 DB instance) before scaling to separate physical DB servers.
  • Replacing SQL JOINs: Use API Aggregation (BFF/Gateway) or CQRS (pre-aggregate data via CDC into a denormalized Read DB).
  • Replacing Foreign Keys: Store logical string/integer IDs (user_id) without database-enforced foreign key constraints.

11. Related Decisions