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

Lesson 4: Service Decomposition — Bounded Context & Service Boundaries

Service separation method based on Bounded Context. Define service boundaries properly, avoid distributed monolith. Decompose by subdomain vs decompose by business capability strategy. Context Mapping patterns.

🏗️ Architecture — Lesson 4 Lesson 4: Service Decomposition — Bounded Context & Service Boundaries

Microservices & Micro Frontend system design — From basics to Production

Part 2: Designing Microservices Backend

xdev.asia

Introduction

Service separation is the most important architectural decision when moving to Microservices. Divided too small → complexity explodes. Divided too large → distributed monolith. This article guides a systematic method to properly define service boundaries.

Service Decomposition — decomposes the system into microservices


1. Principle of separation

1.1 Single Responsibility for Services

Each service is responsible for a unique business capability:

  • User Service → User lifecycle management (register, login, profile)
  • Product Service → Product catalog, search, reviews
  • Order Service → Order processing, fulfillment, history

1.2 Two main strategies

Decompose by Business Capability:

Based on the business functions the organization provides:

E-Commerce Business Capabilities:
├── Customer Management   → User Service
├── Product Management    → Product Service
├── Order Management      → Order Service
├── Payment Processing    → Payment Service
├── Inventory Management  → Inventory Service
└── Shipping & Delivery   → Shipping Service

Decompose by Subdomain (DDD):

Based on subdomains identified via DDD:

Core Subdomains (competitive advantage):
├── Product Catalog → Product Service (custom-built, best team)
├── Order Processing → Order Service (complex logic)

Supporting Subdomains (necessary but not differentiating):
├── Inventory → Inventory Service
├── Customer Profile → User Service

Generic Subdomains (solved problems):
├── Authentication → Keycloak (off-the-shelf)
├── Payment Gateway → Stripe integration
├── Email → SendGrid/SES

1.3 Correct service boundaries signs

  • Service can be developed, deployed, scaled independently
  • Changes in service A seldom require changes in service B
  • Each service has its own database (no shared tables)
  • Teams can work on the service without needing to coordinate with other teams
  • Service has cohesive API — closely related endpoints

2. Context Mapping Patterns

Once you have identified Bounded Contexts, you need to define the relationship between them:

2.1 Partnership

The two teams cooperate closely, jointly developing the interface:

Product Team ←→ Search Team
(cùng định nghĩa product schema cho search indexing)

2.2 Customer-Supplier

Upstream (supplier) provides data/API, Downstream (customer) consumes:

Product Service (Supplier) → Order Service (Customer)
(Order Service cần product info nhưng không thay đổi product)

2.3 Anti-Corruption Layer (ACL)

Transformation layer to protect domain model from external/legacy systems:

┌──────────┐     ┌─────┐     ┌──────────────┐
│ Order    │ ──► │ ACL │ ──► │ Legacy ERP   │
│ Service  │     │     │     │ (SOAP/XML)   │
└──────────┘     └─────┘     └──────────────┘
ACL convert REST/JSON ↔ SOAP/XML

3. Anti-patterns should be avoided

3.1 Distributed Monolith

❌ Services phụ thuộc chặt chẽ:
Service A → Service B → Service C → Service A (circular!)
Kết quả: phải deploy A, B, C cùng lúc = worse than monolith

3.2 Nano-services

❌ Chia quá nhỏ:
├── ProductNameService
├── ProductPriceService
├── ProductImageService
└── ProductReviewService

✅ Chia hợp lý:
└── ProductService (gom lại thành 1 service)

3.3 Shared Database

❌ Nhiều services dùng chung DB:
Service A ──┐
Service B ──┼──► Shared PostgreSQL (products table)
Service C ──┘
Thay đổi schema → break tất cả services

✅ Database per Service:
Service A → DB_A
Service B → DB_B (replicate data nếu cần)
Service C → DB_C

4. Hands-on: Separating E-Commerce Platform

Applicable to projects throughout the series:

E-Commerce Platform Services:

┌─────────────────────────────────────────┐
│ User Service (Supporting)               │
│ - Registration, Login, Profile          │
│ - PostgreSQL (users, addresses)         │
│ - Team: 2-3 devs                       │
├─────────────────────────────────────────┤
│ Product Service (Core)                  │
│ - Catalog, Search, Reviews, Categories  │
│ - PostgreSQL + Elasticsearch            │
│ - Team: 3-4 devs                       │
├─────────────────────────────────────────┤
│ Cart Service (Supporting)               │
│ - Add/Remove items, Apply coupon        │
│ - Redis (fast, ephemeral)              │
│ - Team: 2 devs                         │
├─────────────────────────────────────────┤
│ Order Service (Core)                    │
│ - Place order, Track, History           │
│ - PostgreSQL (orders, order_items)      │
│ - Team: 3-4 devs                       │
├─────────────────────────────────────────┤
│ Payment Service (Generic)               │
│ - Stripe/VNPay integration              │
│ - PostgreSQL (transactions)            │
│ - Team: 2 devs                         │
└─────────────────────────────────────────┘

Summary

PrinciplesDescription
Divide by DomainUse DDD Bounded Context, not divided by technical layer
Loosely CoupledService A changes without needing to deploy Service B
High CohesionRelated functions are located in the same service
Own DataEach service has its own database
Right SizeNot too big (monolith), not too small (nano-service)

Next article: Lesson 5: API Design Masterclass — REST, GraphQL & gRPC