MVP, 10x evolution và complexity budget
Senior design không chỉ cần scale được. Một thiết kế tốt còn phải biết hoãn complexity, biết khi nào nên tiến hóa, và luôn có đường migration/rollback an toàn thay vì rewrite toàn bộ hệ thống.
1. MVP baseline: ship được, quan sát được, ít moving parts
Baseline hợp lý thường là managed relational database, ứng dụng stateless, object storage/CDN cho file/static content, và chỉ thêm queue khi workload thực sự cần tách bất đồng bộ. Mục tiêu là giảm số thành phần phải vận hành để đội ngũ có thể ship nhanh, debug dễ và quan sát hệ thống rõ ràng.
Ngay từ MVP, đừng chỉ ghi “sẽ scale sau”. Hãy ghi các trigger nâng cấp có thể đo được: QPS/throughput, dung lượng storage, p99 latency, availability/SLO, mức độc lập giữa team/tenant, hoặc yêu cầu compliance. Trigger biến evolution từ cảm tính thành decision dựa trên evidence.
| Thành phần MVP | Vì sao thường đủ lúc đầu | Trigger cần xem xét nâng cấp |
|---|---|---|
| Managed relational DB | Transaction, indexing, backup và vận hành cơ bản đã có sẵn | Write saturation, storage/IO limit, p99 query tăng, tenancy/compliance cần isolation |
| Stateless app | Dễ scale horizontal và deploy/rollback | CPU/memory saturation, cold-start/runtime limit, stateful workflow xuất hiện |
| Object storage + CDN | Tách binary/static traffic khỏi app/database | Egress/caching policy, regional latency, lifecycle/compliance thay đổi |
| Queue khi thật cần | Không thêm distributed semantics sớm | Request path quá dài, burst cần buffer, retry/background processing cần tách |
2. Evolution sequence: thay đổi theo bottleneck có evidence
Chuỗi tiến hóa gợi ý từ BK là: Measure bottleneck → vertical/right-size → index/query → cache/read replica → async workload → partition/archive → regionalization. Đây không phải checklist bắt buộc theo đúng thứ tự; mỗi bước chỉ nên xảy ra khi metric chứng minh nó xử lý bottleneck hiện tại, và mỗi thay đổi phải có kế hoạch migration cùng rollback.
| Bước | Câu hỏi trước khi làm | Evidence nên có | Rollback/Migration concern |
|---|---|---|---|
| 1. Measure | Component nào thực sự gây giới hạn? | CPU, IO, queue age, cache hit, DB waits, p95/p99, saturation | Thiết lập baseline và success criterion trước thay đổi |
| 2. Vertical / right-size | Có thể giải quyết bằng cấu hình/capacity đơn giản hơn không? | Utilization + headroom + cost curve | Downtime, resize window, quota |
| 3. Index / query | Đang mua thêm hardware để che query xấu? | Query plan, scanned rows/bytes, lock/wait time | Index build cost, write amplification |
| 4. Cache / read replica | Read nào lặp lại? Staleness cho phép bao nhiêu? | Read/write ratio, hit rate dự kiến, replica lag | Invalidation, consistency, fallback khi cache/replica lỗi |
| 5. Async workload | Phần nào không cần hoàn tất trong request? | Request critical path, burst profile, retry rate | Idempotency, DLQ/retry, user-visible state |
| 6. Partition / archive | Data/traffic có key tự nhiên để chia không? | Hot keys, data growth, working-set size | Rebalancing, cross-partition query, dual-read/write |
| 7. Regionalization | Latency/RPO/RTO có thực sự yêu cầu nhiều region? | User geography, outage model, SLO | Replication conflict, failover/failback, data sovereignty |
Complexity budget
Mỗi cache, queue, replica, partition hoặc region mới đều tạo thêm state, failure mode, observability và on-call burden. Vì vậy “có thể scale” chưa đủ; cần trả lời thêm: complexity này đang mua được requirement nào, và metric nào cho thấy đáng trả giá?
3. Build vs buy: tính total cost, không chỉ bill hạ tầng
Managed service thường giảm toil và rút ngắn thời gian vận hành, nhưng có thể đi kèm chi phí cao hơn ở một số workload, service limits, lock-in và egress. Self-host tăng control nhưng chuyển chi phí sang expertise, capacity planning, patching, upgrade, backup, security và on-call. Vì vậy phải đánh giá total cost, không chỉ compute/storage.
| Cost dimension | Managed service | Self-host |
|---|---|---|
| Compute / storage / network | Giá dịch vụ và tier có thể cao hơn nhưng dễ elasticity | Có thể tối ưu sâu hơn nếu workload ổn định và đội ngũ có năng lực |
| Engineering | Ít code/automation cho undifferentiated operations | Cần xây tooling, automation, upgrade path |
| Incident / on-call | Một phần trách nhiệm nằm ở provider, nhưng app vẫn phải xử lý failure | Đội ngũ sở hữu toàn bộ incident surface |
| Compliance / governance | Có certification/control sẵn nhưng phải map đúng shared responsibility | Control cao hơn nhưng evidence/audit do đội tự xây |
| Lock-in / exit cost | API, data model, egress và migration có thể tạo switching cost | Ít lock-in vendor hơn nhưng vẫn có lock-in vào stack/operations nội bộ |
Infrastructure + Network/Egress + Engineering time + Operations/On-call + Incident impact + Compliance/Governance + Migration/Exit cost
4. 10x constraint: “10x” phải chỉ rõ thứ gì tăng
Khi reviewer hỏi “nếu tăng 10x thì sao?”, câu trả lời tốt không phải “thêm microservices/sharding”. Hãy nêu component chạm limit đầu tiên và metric chứng minh. 10x reads khác hoàn toàn 10x writes, 10x data volume, 10x tenants hay 10x regions.
| 10x ở đâu? | Pressure thường tăng | Evolution targeted có thể cân nhắc |
|---|---|---|
| Reads | DB read CPU/IO, repeated queries, network | Index/query tuning, cache, read replica |
| Writes | Lock/contention, WAL/log, storage IOPS | Batching, async, data model change, partition khi có evidence |
| Data volume | Working set, backup/restore, scan cost | Lifecycle, archive, tiering, partition |
| Tenants | Noisy neighbor, isolation, metadata/cardinality | Quota, sharding/isolation theo tenant tier |
| Regions | Replication, consistency, failover, compliance | Regionalization với explicit data ownership và RPO/RTO |
5. Design review: truy được requirement, state, capacity và cost
Checklist gốc của BK nên được dùng như gate trước khi chốt design:
- Mỗi component phải truy ngược được về requirement hoặc estimate cụ thể.
- Mỗi state phải có owner và source of truth rõ ràng.
- Mỗi cache / queue / replica phải có consistency model và capacity assumption.
- Phải mô tả overload, degraded và recovery behavior, không chỉ happy path.
- Phải có migration, cost và “not now” list để kiểm soát complexity.
Câu hỏi review thực chiến
- Metric nào sẽ buộc chúng ta thay đổi kiến trúc, và threshold hiện tại là gì?
- Nếu component mới fail, hệ thống degrade ra sao? Có bypass/fallback không?
- Migration có cần dual-write/dual-read/backfill không, và rollback boundary ở đâu?
- Chi phí tăng tuyến tính theo traffic/data hay có “cost cliff” tại một tier/quota nào?
- Điều gì chủ động không làm bây giờ, và trigger nào sẽ mở lại quyết định đó?
6. Mini exercise
Giả sử một API hiện có 2.000 read QPS, 200 write QPS, p99 140 ms và DB CPU 45%. Trong 12 tháng, product dự báo read tăng 10x nhưng write chỉ tăng 2x. Hãy trả lời:
- Metric nào cần đo thêm trước khi quyết định?
- Component nào có khả năng chạm limit đầu tiên?
- Bước evolution nhỏ nhất bạn thử trước là gì?
- Success criterion và rollback condition là gì?
- Bạn sẽ ghi gì vào “not now” list?
Mục tiêu bài tập: chứng minh bạn có thể chuyển từ “10x” mơ hồ sang một evolution decision có evidence, cost và rollback.