Chuyển đến nội dung chính

Lesson 7: Database per Service & Polyglot Persistence

Why does each service need its own database? Strategy for choosing the right database: PostgreSQL, MongoDB, Redis, Elasticsearch. Shared database anti-pattern. Data isolation, schema ownership and migration strategy.

🏗️ Architecture — Lesson 7 Lesson 7: Database per Service & Polyglot Persistence

Microservices & Micro Frontend system design — From basics to Production

Part 3: Data Architecture in Microservices

xdev.asia

Introduction

"Database per Service" is the foundation pattern of Microservices. Without it, you don't have real microservices — only modules sharing the same database (distributed monolith). This article explains why, how to choose the right DB, and how to handle data sharing.

Database per Service — each service owns its own database


1. Why Database per Service?

1.1 Shared Database — The Road to Distributed Monolith

❌ Shared Database Anti-pattern:
┌────────┐ ┌────────┐ ┌────────┐
│User µS │ │Order µS│ │Payment │
└───┬────┘ └───┬────┘ └───┬────┘
    │          │          │
    └──────────┼──────────┘
               ▼
    ┌─────────────────────┐
    │  Shared PostgreSQL  │
    │  ├── users          │  ← ai own schema này?
    │  ├── orders         │  ← coupling tại data layer
    │  ├── payments       │  ← thay đổi schema = break all
    │  └── products       │
    └─────────────────────┘

Problem:

  • Schema changes affect all services
  • Cannot scale database independently
  • Tight coupling — deployment must be at the same time
  • You cannot use different databases for different use cases

1.2 Database per Service

✅ Database per Service:
┌────────┐    ┌────────┐    ┌────────┐
│User µS │    │Order µS│    │Cart µS │
└───┬────┘    └───┬────┘    └───┬────┘
    │             │             │
    ▼             ▼             ▼
┌────────┐  ┌────────┐    ┌────────┐
│PostgreSQL│ │PostgreSQL│  │ Redis  │
│(users)  │  │(orders) │   │(carts) │
└─────────┘  └─────────┘  └────────┘

Mỗi service own data riêng.
Schema changes chỉ ảnh hưởng 1 service.
Có thể chọn DB phù hợp nhất cho use case.

2. Polyglot Persistence — Choose the right DB

2.1 Decision Matrix

Use CaseDatabaseWhy
User profiles, OrdersPostgreSQLACID, relational, mature
Product catalogPostgreSQL + ElasticsearchRelational + Full-text search
Shopping cartRedisFast, ephemeral, TTL support
Session storeRedisIn-memory, fast expiry
Activity log, EventsMongoDB / KafkaSchema-flexible, append-only
RecommendationsNeo4j / RedisGraph relationships / Caching
Analytics/BIClickHouse / BigQueryColumnar, fast aggregation

2.2 E-Commerce Platform Database Design

┌─────────────────────────────────────────────┐
│ User Service → PostgreSQL                   │
│   users, addresses, preferences             │
├─────────────────────────────────────────────┤
│ Product Service → PostgreSQL + Elasticsearch│
│   products, categories, reviews (PG)        │
│   search index (ES)                         │
├─────────────────────────────────────────────┤
│ Cart Service → Redis                        │
│   cart:{userId} → JSON (items, quantities)  │
│   TTL: 7 days (auto-expire abandoned carts) │
├─────────────────────────────────────────────┤
│ Order Service → PostgreSQL                  │
│   orders, order_items, order_status_history  │
├─────────────────────────────────────────────┤
│ Payment Service → PostgreSQL                │
│   transactions, refunds, payment_methods    │
└─────────────────────────────────────────────┘

3. Data Sharing Patterns

When Service A needs data from Service B:

3.1 API Composition

Service A calls Service B's API when it needs data. Simple but creates runtime dependencies.

3.2 Event-Carried State Transfer

Service B publishes events containing data → Service A saves a local copy.

ProductService publishes: ProductUpdated {id, name, price, image}
OrderService subscribes → lưu product snapshot trong order_items
→ Không cần gọi ProductService khi hiển thị order history

3.3 CQRS (see details in Lesson 9)

Create read-optimized views from events — dedicated query service.


4. Schema Migration Strategy

Each service manages its own schema:

  • Flyway / Liquibase (Java) or Prisma Migrate / Knex (Node.js)
  • Migration scripts versioned in source code
  • Backward-compatible changes: add column (nullable), add table
  • Breaking changes: multi-phase migration (add new → migrate data → remove old)

Summary

  • Database per Service is non-negotiable for real microservices
  • Select DB according to use case (Polyglot Persistence)
  • Data sharing via Events (preferred) or API calls
  • Schema migration is the responsibility of each service team

Next article: Lesson 8: Saga Pattern & Distributed Transactions