EngineeringSenior DeveloperTraining Sessions

Session 15 - System Design Thinking: Từ Requirements Đến Architecture

Session cuối cùng, tổng hợp tất cả. Không phải về tools hay code, mà về cách suy nghĩ khi đối mặt với bài toán "thiết kế hệ thống X". Đây là kỹ năng phân biệt senior với architect.


Mục tiêu

  • Framework suy nghĩ khi design hệ thống
  • Trade-offs - mọi quyết định đều có giá
  • Capacity planning - tính toán cơ bản
  • Decision records - document tại sao chọn A thay B

1) Framework: 4 Bước Design

Step 1: CLARIFY (Làm rõ yêu cầu)
  "Hệ thống cần phục vụ bao nhiêu users?"
  "Peak load bao nhiêu requests/giây?"
  "Data cần retain bao lâu?"
  "Tính availability cần bao nhiêu % (99.9%? 99.99%)?"
  "Budget là gì?"

Step 2: ESTIMATE (Tính toán cơ bản)
  Traffic: 10M users → 1% active/ngày = 100K DAU
  QPS: 100K DAU × 10 requests/user / 86,400 giây ≈ 12 QPS (avg)
  Peak: 12 × 10 = 120 QPS (peak hours)
  Storage: 100K users × 1KB = 100MB (users)
  Bandwidth: 120 QPS × 2KB response = 240 KB/s

Step 3: DESIGN (High-level architecture)
  Components, data flow, technology choices
  → Vẽ diagram, xác định bottlenecks

Step 4: DEEP DIVE (Chi tiết areas quan trọng)
  → Database schema
  → Caching strategy
  → Failure handling
  → Security

2) Trade-offs - Mọi Quyết Định Có Giá

Monolith vs Microservices

Monolith:
  ✅ Simple development, simple deployment
  ✅ No network overhead, strong consistency
  ✅ Easy debugging (1 process, 1 log)
  ❌ Scale = scale toàn bộ app
  ❌ Team bottleneck (1 codebase, merge conflicts)
  ❌ Technology lock-in (1 framework)

Microservices:
  ✅ Independent scale, deploy, technology
  ✅ Team autonomy
  ✅ Fault isolation
  ❌ Network complexity (latency, failure, consistency)
  ❌ Operational overhead (monitoring, tracing, deployment)
  ❌ Data consistency challenge
Quyết định: KHÔNG phải "cái nào tốt hơn"
Mà là: "Cost nào bạn chấp nhận được?"

Team 5 người, MVP → Monolith → giá trị = ship nhanh
Team 50 người, 10 modules → Microservices → giá trị = team autonomy
Team 10 người, growing → Modular Monolith → giá trị = prepare for split

SQL vs NoSQL

SQL (Azure SQL, PostgreSQL):
  ✅ ACID transactions, complex queries, JOINs
  ✅ Schema enforcement, data integrity
  ❌ Vertical scaling limits
  ❌ Schema migration overhead
  → Best for: OLTP, financial, orders, inventory

NoSQL (Cosmos DB, MongoDB):
  ✅ Horizontal scaling, flexible schema
  ✅ Low latency, global distribution
  ❌ No JOINs, limited transactions
  ❌ Data duplication (denormalization)
  → Best for: catalog, sessions, logs, real-time

Sync vs Async Communication

Sync (REST, gRPC):
  ✅ Simple, immediate response
  ✅ Easy to understand flow
  ❌ Coupling: caller PHẢI chờ, callee PHẢI available
  ❌ Latency: mỗi hop thêm latency
  → Dùng khi: caller CẦN response ngay

Async (Message Queue, Events):
  ✅ Decoupled: producer không cần biết consumer
  ✅ Resilient: message retry nếu consumer down
  ❌ Eventual consistency
  ❌ Harder to trace/debug
  → Dùng khi: eventual consistency OK, fire-and-forget

3) Capacity Planning - Back-of-envelope

Bài toán: eCommerce platform, 1M users

Users:
  1M registered, 100K DAU, 10K concurrent
  
Traffic:
  Browsing: 10K concurrent × 1 req/3 giây = 3,333 QPS
  Search: 1K QPS
  Checkout: 50 QPS (peak)
  → Total: ~5K QPS peak

Storage:
  Orders: 10K orders/day × 2KB × 365 days = 7.3 GB/year
  Products: 100K products × 5KB = 500 MB
  Images: 100K products × 5 images × 500KB = 250 GB
  Users: 1M × 1KB = 1 GB
  → Database: ~10 GB/year
  → Blob: ~250 GB (CDN cached)

Infrastructure estimate:
  API: 5K QPS → 2-3 Container App instances (scale to 10)
  Database: Azure SQL Standard (DTU) hoặc Serverless
  Cache: Redis 6GB (product catalog, sessions)
  Storage: Blob + CDN
  → Cost: ~$300-500/month

4) Architecture Decision Records (ADR)

markdown
# ADR-001: Chọn Modular Monolith cho Phase 1

## Context
Team 8 người, product mới, cần ship MVP trong 3 tháng.
Dự kiến scale đến 50K DAU trong 6 tháng.

## Decision
Chọn Modular Monolith (thay vì Microservices).

## Reasoning
- Team nhỏ: overhead của microservices > benefit
- MVP: cần ship nhanh, iterate nhanh
- Scale 50K: 1 server đủ handle
- Modules tách rõ: dễ extract microservices sau nếu cần

## Consequences
- ✅ Ship nhanh hơn 2-3x so với microservices
- ✅ Simple deployment, debugging
- ⚠️ Cần discipline giữ module boundaries
- ⚠️ Scale vertical trước, cần plan cho horizontal nếu > 100K DAU

## Status: Accepted
## Date: 2024-01-15

ADR quan trọng vì: 6 tháng sau, dev mới join hỏi "tại sao không dùng microservices?" → đọc ADR → hiểu context → không refactor vô ích.


5) Real-World Decision Framework

Khi đối mặt architecture decision, hỏi:

1. REQUIREMENTS
   □ Functional: hệ thống CẦN làm gì?
   □ Non-functional: performance, availability, security, scalability?
   □ Constraints: budget, team size, timeline, existing tech?

2. OPTIONS
   □ Liệt kê ≥2 options (LUÔN có alternative!)
   □ Option A: ưu điểm gì? nhược gì?
   □ Option B: ưu điểm gì? nhược gì?
   □ Option C (nếu có)

3. TRADE-OFFS
   □ Option nào phù hợp constraints HIỆN TẠI?
   □ Cost of change: nếu sai, đổi khó cỡ nào?
   □ Reversible vs Irreversible decision?
   □ YAGNI: có thực sự CẦN ngay bây giờ?

4. DECISION
   □ Chọn option nào? Tại sao?
   □ Document trong ADR
   □ Communicate với team

6) Sai Lầm Phổ Biến Khi Design

1. Resume-Driven Development
   "Dùng Kubernetes + Kafka + Microservices cho app TODO list"
   → Chọn tech vì muốn học, không phải vì phù hợp

2. Premature Optimization
   "Caching layer, read replicas, sharding từ ngày 1"
   → 0 users nhưng infra cho 1M users

3. Cargo Cult Architecture
   "Netflix dùng microservices, mình cũng phải dùng"
   → Netflix có 2000+ engineers. Bạn có 5.

4. Not Designing for Failure
   "External API sẽ luôn available"
   → Murphy's Law: nếu có thể fail, nó SẼ fail

5. Ignoring Operations
   "Thiết kế xong deploy thế nào tính sau"
   → Monitoring, logging, deployment = PART of design

Master Checklist ✅

□ Clarify requirements TRƯỚC khi design?
□ Back-of-envelope estimation cho traffic/storage?
□ Ít nhất 2 options cho mỗi major decision?
□ Trade-offs rõ ràng (không có "best", chỉ có "best for THIS context")?
□ ADR cho major decisions?
□ Design for failure (retry, circuit breaker, fallback)?
□ Operations considered (logging, monitoring, deployment)?
□ KISS: simplest solution that WORKS?

Tư duy master: Architecture tốt không phải architecture phức tạp nhất. Mà là architecture đơn giản nhất giải quyết được problem hiện tại, và dễ evolve khi requirements thay đổi. "Make it work, make it right, make it fast" - THEO THỨ TỰ ĐÓ.