Giao diện
🏛️ MONOLITH VS MICROSERVICES
Trade-offs, Modular Monolith, và Database per Service
📋 Prerequisites
📚 Kiến thức cần có
Trước khi bắt đầu module này, hãy đảm bảo bạn đã nắm vững:
- 🗃️ Database Design - SQL vs NoSQL, Sharding strategies
- 📈 Scalability - Horizontal vs Vertical Scaling
- 📊 Consistency Models - ACID vs BASE trade-offs
🎯 Mục tiêu
Sau khi hoàn thành module này, bạn sẽ:
- Hiểu rõ trade-offs giữa Monolith và Microservices
- Biết khi nào nên chọn Modular Monolith
- Nắm vững nguyên tắc "Database per Service"
- Nhận diện và tránh Distributed Monolith anti-pattern
🏰 The Majestic Monolith
Monolith không phải là "xấu"
Có một sự thật mà nhiều developer bỏ qua: những hệ thống lớn nhất thế giới vẫn chạy trên Monolith.
📊 Case Study: Stack Overflow
Stack Overflow - website Q&A lớn nhất thế giới với 100+ triệu monthly visitors - chạy trên một Monolith duy nhất.
| Metric | Giá trị |
|---|---|
| Monthly Visitors | 100+ triệu |
| Questions | 23+ triệu |
| Answers | 34+ triệu |
| Architecture | Monolith (ASP.NET) |
| Servers | ~9 web servers |
| Database | 2 SQL Server clusters |
💡 Tại sao Stack Overflow chọn Monolith?
- Simplicity: Một codebase, một deployment, một team hiểu toàn bộ hệ thống
- Performance: Không có network latency giữa các services
- Debugging: Stack trace đầy đủ, dễ trace bugs
- Cost: Ít infrastructure, ít DevOps overhead
🛒 Case Study: Shopify
Shopify - nền tảng e-commerce với $175 billion GMV - cũng chạy trên Modular Monolith.
Shopify Architecture (2023):
├── Core Monolith (Ruby on Rails)
│ ├── Checkout Module
│ ├── Inventory Module
│ ├── Orders Module
│ └── Payments Module
└── Extracted Services (chỉ khi cần thiết)
├── Storefront Renderer
└── Background Jobs"We've been running a monolith for 15 years. It's not about monolith vs microservices, it's about modular vs coupled." — Shopify Engineering
🧱 Modular Monolith Architecture
Modular Monolith là kiến trúc kết hợp ưu điểm của cả hai thế giới:
- Simplicity của Monolith (single deployment)
- Modularity của Microservices (clear boundaries)
Nguyên tắc thiết kế
┌─────────────────────────────────────────────────────────┐
│ MODULAR MONOLITH │
├─────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Module A │ │ Module B │ │ Module C │ │
│ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │
│ │ │ API │ │ │ │ API │ │ │ │ API │ │ │
│ │ ├───────┤ │ │ ├───────┤ │ │ ├───────┤ │ │
│ │ │Domain │ │ │ │Domain │ │ │ │Domain │ │ │
│ │ ├───────┤ │ │ ├───────┤ │ │ ├───────┤ │ │
│ │ │ Data │ │ │ │ Data │ │ │ │ Data │ │ │
│ │ └───────┘ │ │ └───────┘ │ │ └───────┘ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ SHARED DATABASE │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │Schema A │ │Schema B │ │Schema C │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘Quy tắc vàng của Modular Monolith
| Quy tắc | Mô tả |
|---|---|
| 1. Clear Boundaries | Mỗi module có API riêng, không truy cập trực tiếp internal của module khác |
| 2. Schema Isolation | Mỗi module sở hữu schema riêng trong database |
| 3. Communication via API | Modules giao tiếp qua public interfaces, không qua database joins |
| 4. Independent Testing | Mỗi module có thể test độc lập |
Code Example: Module Boundaries
typescript
// ❌ BAD: Modules truy cập trực tiếp database của nhau
class OrderService {
async createOrder(userId: string, items: Item[]) {
// Truy cập trực tiếp bảng users - VI PHẠM boundary!
const user = await db.query('SELECT * FROM users WHERE id = ?', [userId]);
// ...
}
}
// ✅ GOOD: Modules giao tiếp qua API
class OrderService {
constructor(private userModule: UserModuleAPI) {}
async createOrder(userId: string, items: Item[]) {
// Gọi qua public API của User Module
const user = await this.userModule.getUserById(userId);
// ...
}
}🔬 Microservices: Định nghĩa Đúng
⚠️ Định nghĩa quan trọng
Microservices = Deploy độc lập + Database riêng
Nếu thiếu một trong hai yếu tố này, bạn KHÔNG có Microservices.
Hai điều kiện bắt buộc
1. Deploy độc lập (Independent Deployment)
Mỗi service có thể:
- Build riêng
- Test riêng
- Deploy riêng
- Scale riêng
yaml
# Kubernetes deployment - mỗi service độc lập
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3 # Scale riêng
template:
spec:
containers:
- name: order-service
image: order-service:v2.1.0 # Version riêng
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
spec:
replicas: 5 # Scale khác với order-service
template:
spec:
containers:
- name: payment-service
image: payment-service:v1.8.0 # Version khác2. Database per Service (Nguyên tắc cốt lõi)
🗃️ DATABASE PER SERVICE
Đây là nguyên tắc QUAN TRỌNG NHẤT của Microservices.
Mỗi service SỞ HỮU data của mình:
- Không service nào được truy cập trực tiếp database của service khác
- Giao tiếp data chỉ qua API hoặc Events
┌─────────────────────────────────────────────────────────┐
│ MICROSERVICES │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │Order Service│ │Payment Svc │ │User Service │ │
│ │ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │ │
│ │ │ API │ │ │ │ API │ │ │ │ API │ │ │
│ │ ├───────┤ │ │ ├───────┤ │ │ ├───────┤ │ │
│ │ │Domain │ │ │ │Domain │ │ │ │Domain │ │ │
│ │ └───────┘ │ │ └───────┘ │ │ └───────┘ │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ PostgreSQL │ │ MySQL │ │ MongoDB │ │
│ │ (Orders) │ │ (Payments) │ │ (Users) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘Tại sao Database per Service quan trọng?
| Lợi ích | Giải thích |
|---|---|
| Loose Coupling | Services không phụ thuộc vào schema của nhau |
| Independent Scaling | Có thể chọn database phù hợp cho từng service |
| Fault Isolation | Database của service A chết không ảnh hưởng service B |
| Team Autonomy | Team sở hữu toàn bộ stack của service |
☠️ Distributed Monolith: The Worst of Both Worlds
☠️ ANTI-PATTERN ALERT: DISTRIBUTED MONOLITH
Distributed Monolith là khi bạn có:
- Nhiều services (complexity của Microservices)
- Nhưng vẫn tightly coupled (không có lợi ích của Microservices)
Kết quả: Bạn phải chịu tất cả nhược điểm của cả hai kiến trúc mà không có ưu điểm nào.
Dấu hiệu nhận biết Distributed Monolith
| Dấu hiệu | Mô tả |
|---|---|
| 🔗 Shared Database | Nhiều services truy cập cùng một database |
| 🔄 Synchronized Deployments | Phải deploy nhiều services cùng lúc |
| 💥 Cascading Failures | Service A chết → Service B, C, D cũng chết |
| 🧪 Integration Testing Hell | Không thể test một service độc lập |
| 📞 Synchronous Chains | A → B → C → D (chain of sync calls) |
Ví dụ: Shared Database Anti-pattern
❌ DISTRIBUTED MONOLITH (Shared Database)
┌─────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │Order Service│ │Payment Svc │ │User Service │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ SHARED DATABASE │ ← Coupling point! │
│ │ ┌─────┬─────┬────┐ │ │
│ │ │users│orders│pay │ │ │
│ │ └─────┴─────┴────┘ │ │
│ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
Vấn đề:
- Order Service đọc trực tiếp bảng users
- Payment Service JOIN với bảng orders
- Thay đổi schema → phải update TẤT CẢ servicesHậu quả của Distributed Monolith
typescript
// Ví dụ: Synchronous Call Chain (Anti-pattern)
class OrderService {
async createOrder(userId: string, items: Item[]) {
// 1. Gọi User Service (sync)
const user = await this.userService.getUser(userId); // 100ms
// 2. Gọi Inventory Service (sync)
const stock = await this.inventoryService.checkStock(items); // 150ms
// 3. Gọi Payment Service (sync)
const payment = await this.paymentService.charge(user, total); // 200ms
// 4. Gọi Notification Service (sync)
await this.notificationService.sendEmail(user.email); // 100ms
// Total latency: 550ms (cộng dồn!)
// Nếu BẤT KỲ service nào chết → toàn bộ request fail
}
}🔧 Raizo's Reality Check
"Tôi đã thấy nhiều team 'chuyển sang Microservices' nhưng thực ra chỉ tạo ra Distributed Monolith. Họ có 20 services nhưng vẫn phải deploy cùng lúc, vẫn share database, và mỗi lần có bug thì phải debug qua 5-6 services.
Kết quả? Latency tăng 10x, debugging khó hơn 100x, và team vẫn không thể deploy độc lập. Đó là worst of both worlds."
📊 So sánh: Modular Monolith vs Microservices
Architecture Comparison Diagram
Decision Matrix
| Tiêu chí | Modular Monolith | Microservices | Distributed Monolith |
|---|---|---|---|
| Deployment | Single unit | Independent | Phải sync |
| Database | Shared (isolated schemas) | Per service | Shared (coupled) |
| Complexity | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| Team Size | 5-50 | 50+ | N/A (anti-pattern) |
| Debugging | Easy | Hard | Very Hard |
| Latency | Low | Medium | High |
| Scalability | Vertical + some Horizontal | Full Horizontal | Limited |
| Recommendation | ✅ Most teams | ✅ Large orgs | ❌ Avoid |
🎓 Giáo sư Tom's Insight
🎓 Góc nhìn Lý thuyết
Conway's Law và Architecture
"Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations." — Melvin Conway, 1967
Ý nghĩa thực tế:
- Nếu bạn có 1 team → Monolith là tự nhiên
- Nếu bạn có nhiều teams độc lập → Microservices có thể hợp lý
Evolutionary Architecture
Kiến trúc tốt nhất là kiến trúc tiến hóa theo tổ chức:
Startup (5 người) → Monolith
Scale-up (20 người) → Modular Monolith
Enterprise (100+ người) → Microservices (có thể)The Fallacy of "Future-Proofing"
Nhiều team chọn Microservices vì "sau này sẽ cần scale". Đây là premature optimization.
Sự thật:
- 90% startups không bao giờ đạt scale cần Microservices
- Chuyển từ Modular Monolith → Microservices dễ hơn nhiều so với việc fix Distributed Monolith
- YAGNI (You Aren't Gonna Need It) áp dụng cho architecture
🔧 Kỹ sư Raizo's Reality Check
🔧 Góc nhìn Thực chiến
"Nếu team dưới 50 người, hãy quên Microservices đi"
"Tôi đã làm việc ở cả startup và Big Tech. Đây là sự thật mà ít ai nói:
Microservices được tạo ra để giải quyết vấn đề của TỔ CHỨC, không phải vấn đề KỸ THUẬT.
Amazon, Netflix, Google chuyển sang Microservices vì họ có hàng nghìn engineers cần làm việc độc lập. Không phải vì Microservices 'tốt hơn'."
Chi phí ẩn của Microservices
| Chi phí | Mô tả |
|---|---|
| DevOps Overhead | CI/CD cho mỗi service, Kubernetes, Service Mesh |
| Observability | Distributed tracing, Log aggregation, Metrics |
| Network Complexity | Service discovery, Load balancing, Circuit breakers |
| Data Consistency | Saga pattern, Eventual consistency, Idempotency |
| Testing | Contract testing, Integration testing across services |
Câu hỏi tự kiểm tra
Trước khi chọn Microservices, hãy trả lời:
- ❓ Team có 50+ engineers không?
- ❓ Có nhiều teams cần deploy độc lập không?
- ❓ Có DevOps maturity để vận hành không?
- ❓ Có sẵn sàng chấp nhận eventual consistency không?
Nếu trả lời "Không" cho bất kỳ câu nào → Chọn Modular Monolith.
💡 Think About It
🤔 Câu hỏi suy ngẫm
Stack Overflow phục vụ 100 triệu users với Monolith. Tại sao nhiều startup 1000 users lại nghĩ họ cần Microservices?
Nếu Shopify - công ty $175 billion GMV - vẫn dùng Modular Monolith, điều đó nói gì về "best practices"?
Conway's Law nói kiến trúc phản ánh tổ chức. Nếu team bạn có 5 người, kiến trúc nào phản ánh đúng nhất?
🎯 Interactive Scenario
🎯 Tình huống: Startup Thương mại Điện tử
Bối cảnh
Bạn là Tech Lead của một startup e-commerce mới thành lập:
| Thông tin | Chi tiết |
|---|---|
| Team size | 5 developers (full-stack) |
| Timeline | MVP trong 3 tháng |
| Expected users | 10,000 users năm đầu |
| Budget | Limited (seed funding) |
| Features | Product catalog, Cart, Checkout, User accounts |
CEO đọc được bài viết về Netflix và muốn xây dựng hệ thống "scalable từ đầu" với Microservices.
Câu hỏi
Bạn sẽ đề xuất kiến trúc nào?
A) Microservices - Tách thành 5 services: User, Product, Cart, Order, Payment
B) Modular Monolith - Một ứng dụng với 5 modules có boundaries rõ ràng
C) Simple Monolith - Một ứng dụng đơn giản, refactor sau
🔧 Raizo's Verdict (nếu chọn A - Microservices)
SAI RỒI! 🚫
"5 người mà đòi làm Microservices? Bạn sẽ dành 80% thời gian cho infrastructure thay vì features.
Với 5 services, bạn cần:
- 5 CI/CD pipelines
- 5 databases
- Service discovery
- API Gateway
- Distributed tracing
- Log aggregation
Team 5 người không có bandwidth cho những thứ này. Bạn sẽ ship MVP trong 12 tháng thay vì 3 tháng, và có thể hết tiền trước khi launch."
✅ Đáp án đúng: B hoặc C
Lựa chọn tối ưu: Modular Monolith (B)
Lý do:
- Team size phù hợp: 5 người có thể hiểu toàn bộ codebase
- Time to market: Ship nhanh hơn 3-5x so với Microservices
- Cost effective: Một server, một database, một deployment
- Future-proof: Dễ dàng extract thành Microservices SAU KHI có product-market fit
Cấu trúc đề xuất
ecommerce-app/
├── src/
│ ├── modules/
│ │ ├── user/ # User domain
│ │ ├── product/ # Product catalog
│ │ ├── cart/ # Shopping cart
│ │ ├── order/ # Order management
│ │ └── payment/ # Payment processing
│ ├── shared/ # Shared utilities
│ └── main.ts
├── database/
│ └── migrations/ # Single DB, separate schemas
└── tests/Khi nào chuyển sang Microservices?
- Team grow lên 20+ engineers
- Có product-market fit rõ ràng
- Có DevOps resources dedicated
- Có bottleneck cụ thể cần scale riêng
:::
📝 Summary
| Concept | Key Takeaway |
|---|---|
| Monolith | Không xấu - Stack Overflow, Shopify vẫn dùng thành công |
| Modular Monolith | Best choice cho hầu hết teams (< 50 engineers) |
| Microservices | Chỉ khi có organizational need, không phải technical need |
| Database per Service | Điều kiện BẮT BUỘC của Microservices |
| Distributed Monolith | Anti-pattern - worst of both worlds |
🚀 Next Steps
Tiếp theo trong Phase 3
👉 Module 3.2: Distributed Transactions →
Học cách xử lý transactions khi data nằm ở nhiều services khác nhau.
Related Topics
| Topic | Liên quan |
|---|---|
| 📊 Consistency Models | ACID vs BASE - nền tảng cho distributed systems |
| 📬 Async Messaging | Event-driven architecture cho loose coupling |
| 🗃️ Database Design | Sharding strategies khi scale |
Case Studies áp dụng
| Case Study | Áp dụng |
|---|---|
| 🐦 Design Twitter | Xem cách Twitter tiến hóa từ Monolith |
| 🚗 Design Uber | Microservices trong ride-sharing |
📖 Further Reading
- MonolithFirst - Martin Fowler
- Modular Monolith - Kamil Grzybek
- Microservices Prerequisites - Martin Fowler