17 KiB
ADR-001 — Kiểu kiến trúc tổng thể của sàn e-commerce là Modular Monolith + managed AWS (P2), không phải ~10 Microservices độc lập (P1)
Tên file: adr/ADR-001_kieu-kien-truc-tong-the-modular-monolith-p2.md
| Status | Proposed |
| Date | 2026-09-15 |
| Người quyết | SA + Tech Lead (theo decision-radar.md §5 — "Cấu trúc hệ thống" đề xuất SA, chốt SA+Tech Lead; EA phủ quyết nếu lệch chuẩn doanh nghiệp). Chưa ký thật — chỉ có Điều phối dự án ký thay theo ngoại lệ DEC-01/DEC-17, xem §Điều kiện chuyển Accepted |
| Người đề xuất | SA (qua skill sa-2-architecture, hoạt động adr) |
| Điểm radar | ~7/10 (chấm lại theo decision-radar.md §2 — xem §Radar dưới; dưới ngưỡng 8 cứng nhưng vẫn cần POC vì ASM-07/ASM-08 chưa xác minh) |
| Supersedes | — |
| Superseded by | — |
| Liên quan | ASR-001 · QAS-005 · QAS-006 · QAS-009 · CON-03 · CON-05 · CON-06 · DRV-04 · DEC-06 · POC-01 · POC-02 · OQ-010 · OQ-012 |
⚠️ ADR bất biến sau khi
Accepted. Muốn đổi quyết định thì viết ADR mới cóSupersedes: ADR-001và đổi trạng thái bản cũ thànhSuperseded by. Không sửa nội dung ADR đã Accepted, không xoá ADR đã Rejected.
1. Bối cảnh
Sàn e-commerce là dự án greenfield (CTX §4.1), quy mô mục tiêu "lớn" (DRV-04: hàng trăm
nghìn SKU, hàng trăm nghìn–hàng triệu user, đỉnh hàng nghìn–chục nghìn concurrent user mùa flash
sale — kịch bản A 2.000 CCU/~400 đơn/giờ, kịch bản B 10.000 CCU/~15.000 đơn/giờ, QAS-009).
OPT_e-commerce_v1.0.md (Bước 4 GĐ1) đã dựng và chấm điểm 3 phương án khả thi (P0/P1/P2) cộng
2 phương án bị loại ở gate cứng (P3/P4) — kết luận khuyến nghị P2 (modular monolith 2–3 nhóm
ECS Fargate + managed AWS, Payment tách riêng), duyệt từng phần bởi PO uỷ quyền tại DEC-06,
nhưng DEC-06 tự ghi rõ chưa thay thế yêu cầu ADR chính thức (kiểu kiến trúc tổng thể là
quyết định thuộc danh mục bắt buộc ADR theo decision-radar.md §3). ASR-001 (chưng cất từ
DEC-06) xác nhận đây là ràng buộc cấu trúc bao trùm toàn bộ hệ thống, ép ra ranh giới container
ở SAD §4. ADR này trả nợ DEC-06/DTM §11 "🟠 Nợ #1"/ADL §8 — không phải quyết định
mới, mà là hình thức hoá quyết định đã có hướng đi tạm.
Ràng buộc đang chi phối:
| Nguồn | Nội dung |
|---|---|
CON-03 |
Cloud AWS bắt buộc (cứng) — loại mọi phương án ngoài AWS ngay từ OPT |
CON-05 |
Số đội/số người thi công chưa xác nhận thật — giả định tạm "team MVP chuẩn" (DEC-02), tham khảo hồ sơ thầu: BE trung bình ~2,6 FTE/tháng trên 7 tháng, đỉnh 10 người toàn dự án |
CON-06 |
PCI-DSS SAQ A + NĐ13/2023 — Payment phải là biên cô lập bất kể chọn P1 hay P2 (áp dụng độc lập với ADR này, xem ADR-002) |
ASR-001 |
Ép ranh giới triển khai 2–3 nhóm ECS Fargate + 1 nhóm Payment riêng; ép dùng SQS/EventBridge thay Kafka/MSK; ép 1 RDS chính schema-per-module |
QAS-005/QAS-006/QAS-009 |
Thông lượng/độ trễ/khả năng mở rộng phải đạt ở kịch bản A/B — input trực tiếp cho POC-01/POC-02 |
Cái đã biết chắc / cái còn là giả định:
| Điều | 🟢 Đã kiểm chứng / 🔴 Giả định | Bằng chứng |
|---|---|---|
| AWS là cloud bắt buộc | 🟢 Đã kiểm chứng | CON-03, xác nhận vòng 3 Q&A brief |
| Payment phải cô lập PCI-DSS SAQ A | 🟢 Đã kiểm chứng | CON-06, pháp luật/hợp đồng đối tác |
SQS FIFO + EventBridge đủ throughput cho OrderPlaced/PaymentConfirmed ở tải đỉnh |
🔴 Giả định (ASM-07) |
POC-01 — chưa chạy |
| 1 cụm RDS chính đủ tải ghi/đọc gộp | 🔴 Giả định (ASM-08) |
POC-02 — chưa chạy |
Team thi công thật khớp giả định "team MVP chuẩn" (DEC-02) |
🔴 Giả định | OQ-010 — Tech Lead chưa xác nhận |
| P2 rẻ hơn P1 ở TCO 3 năm (sơ bộ, số lượng thành phần) | 🟡 Ước lượng có cơ sở | TCO §3.2 (chưa quy đổi VND đầy đủ, đơn giá AWS chưa xác nhận OQ-013) |
2. Phương án đã cân nhắc
Tham chiếu đầy đủ bảng chấm điểm và sơ đồ mức khối đã có ở OPT_e-commerce_v1.0.md §3, §4, §5
— không lặp lại ở đây theo đúng ghi chú người duyệt. Tóm tắt lại đúng mức cần để ra quyết
định.
PA-1 — P1: Modular microservices (~10 service, database-per-service, Kafka/MSK, OpenSearch)
| Mô tả | ~10 service theo bounded-context, mỗi service 1 RDS logic riêng, Kafka/MSK làm xương sống bất đồng bộ, OpenSearch đa node cho search, ECS/EKS auto-scaling theo domain — theo SAD.md v0.2/hồ sơ thầu (OPT §3 P1) |
| Ưu | Đáp ứng DRV Must cao nhất (OPT §4: điểm 5/5) — scale-out độc lập Catalog/Search khỏi Cart/Checkout ngay từ ngày một (DRV-04); ranh giới service rõ, dễ thay/rút từng service riêng lẻ về sau |
| Nhược | Vi phạm Conway rõ với team giả định hiện tại — mỗi BE ôm trung bình 3–4 service (CON-05, OPT §4 tiêu chí 5: P1=2/5); không có bằng chứng team từng vận hành Kafka/MSK/OpenSearch/EKS production (CTX §4.4, OQ-010 mở); effort dựng nền tảng riêng đã ước 70,2 MD (WBS-03, XL, +35% contingency) trước khi làm nghiệp vụ; nhiều thành phần managed độc lập phải vận hành hơn |
| Chi phí đảo ngược | Gộp ngược lại thành ít service hơn (nếu team quá nhỏ để vận hành 10 service) tốn công tái cấu trúc network/DB đáng kể — ước > 4 tuần |
PA-2 — P2: Modular monolith (2–3 nhóm ECS Fargate) + managed AWS, Payment tách riêng (chọn)
| Mô tả | Modular monolith theo domain, chạy 2–3 nhóm ECS Fargate (Nhóm Giao dịch / Nhóm Hỗ trợ), SQS FIFO + EventBridge thay Kafka/MSK, 1 RDS chính schema-per-module, Postgres FTS giai đoạn đầu (hoãn OpenSearch); Payment tách hoàn toàn (network/IAM/DB riêng) — theo OPT §3 P2 |
| Ưu | Khớp Conway với team giả định (OPT §4 tiêu chí 5: P2=5/5); effort nền tảng thấp hơn P1 (-70,2 MD, không cần dựng cụm Kafka/MSK); ít thành phần managed độc lập phải vận hành hơn (chi phí vận hành sơ bộ thấp hơn); rủi ro công nghệ thấp hơn (managed service phổ biến hơn) |
| Nhược | Thua P1 đúng 1 bậc ở tiêu chí "Đáp ứng DRV Must" (4/5 so với 5/5, OPT §4) — scale-out độc lập Catalog/Search khỏi Cart/Checkout kém hơn ở giai đoạn đầu (chung nhóm "Nhóm Giao dịch"); nếu traffic thật vượt xa dự kiến, tách Catalog/Search ra khỏi monolith muộn sẽ tốn hơn tách từ đầu |
| Chi phí đảo ngược | Module hoá rõ theo domain trong code giúp tách thành service riêng về sau có kế hoạch khi có bằng chứng tải thật — nhưng tốn công tách hạ tầng (network, DB, CI/CD riêng) tại thời điểm tách, không miễn phí; ước > 4 tuần nếu tách toàn diện |
PA-0 — Không xây gì (P0, mốc so sánh)
Vi phạm trực tiếp DRV-01 (Must, blocker MVP) — không phải phương án khả thi, chỉ giữ làm mốc
so sánh (OPT §4). Không xét tiếp.
Bảng so sánh (tóm tắt — chi tiết đầy đủ 6 tiêu chí × trọng số ở OPT §4)
| Tiêu chí (trọng số) | P1 | P2 |
|---|---|---|
Đáp ứng DRV Must (25%) |
5 | 4 |
| Chi phí 3 năm sơ bộ (20%) | 2 | 4 |
| Thời gian tới bản chạy được (15%) | 2 | 4 |
| Rủi ro kỹ thuật (15%) | 2 | 4 |
| Năng lực team & vận hành — Conway (15%) | 2 | 5 |
| Khả năng tiến hoá (10%) | 4 | 3 |
| Tổng có trọng số | 2.95 | 4.05 |
Chênh lệch 1.10 điểm — đủ phân biệt theo OPT §4 (không rơi vào bẫy "chênh <0.3").
3. Quyết định
Chọn PA-2 (P2) — Modular monolith + managed AWS, Payment tách riêng.
Toàn sàn e-commerce được tổ chức thành 2–3 nhóm triển khai ECS Fargate (modular monolith theo domain — Nhóm Giao dịch: Identity & Access, Catalog & Inventory, Cart & Order; Nhóm Hỗ trợ: Seller Management, Commission & Payout, Promotion & Loyalty, Review, Notification, Shipping & Fulfillment), cộng 1 Payment Service tách hoàn toàn về mạng/IAM/dữ liệu. Dùng SQS FIFO + EventBridge (không phải Kafka/MSK) và 1 cụm RDS PostgreSQL chính schema-per-module (không phải database-per-service).
Vì sao: Khớp CON-05 (Conway — năng lực team giả định hiện tại), giữ nguyên CON-06 (Payment
cô lập, độc lập với lựa chọn này), và đạt điểm tổng cao nhất trong bộ tiêu chí đã chốt ở OPT §2
(4.05 so với 2.95 của P1).
Phạm vi áp dụng: Toàn bộ sàn e-commerce, đến khi traffic thật tiệm cận kịch bản B × 2
(~20.000 concurrent) mà chưa kiểm chứng lại bằng POC/bài đo thật (xem QAS-009 "Ngoài phạm vi").
Điều kiện chuyển Proposed → Accepted
| Điều kiện | Ai xác nhận | Trạng thái hiện tại |
|---|---|---|
POC-01 PASS (throughput SQS FIFO/EventBridge ≥100 msg/s sustained, p99 ≤2s, 0 mất message) |
Tech Lead + 1 DevOps | Chưa chạy (ARISK-01, OQ-012) |
POC-02 PASS (RDS gộp: p95 write ≤300ms, p95 read ≤200ms, CPU <75%) |
Tech Lead/DBA | Chưa chạy (ARISK-02) |
OQ-010 — Tech Lead xác nhận team thi công thật khớp (hoặc gần khớp) giả định "team MVP chuẩn" |
Tech Lead | Mở |
| AG1 ký thật (PO + Tech Lead, không phải ký thay) | PO + Tech Lead | Mở (OQ-004) |
🔴 Dù radar ước lượng ~7 (< 8 ngưỡng cứng), ADR này vẫn không được chuyển Accepted cho tới
khi cả hai POC chạy xong — vì bản thân ASM-07/ASM-08 (nền tảng của toàn bộ lựa chọn P2)
chưa xác minh; đây là cam kết đã ghi tại OPT §1 "Điều kiện kèm theo" và DEC-06.
4. Phương án bị loại và lý do
| Phương án | Loại vì | Gắn với | Điều kiện nào thì xét lại |
|---|---|---|---|
| P0 — Không xây gì | Vi phạm trực tiếp DRV-01 (Must, blocker MVP) |
DRV-01 |
Không xét lại — không phải phương án khả thi cho một sàn giao dịch |
| P1 — Modular microservices (~10 service) | Vi phạm Conway với team giả định hiện tại (CON-05, mỗi BE ôm 3–4 service); không có bằng chứng team từng vận hành Kafka/MSK/OpenSearch/EKS production (CTX §4.4) |
CON-05, OPT §4 tiêu chí 4/5 |
Nếu OQ-010 xác nhận team thật có kinh nghiệm Kafka/MSK/OpenSearch/EKS production và team đủ lớn (gần đỉnh 10 người đề xuất hồ sơ thầu) — chấm lại theo OPT §9 OQ-010 |
| P3 — Mua/tích hợp nền tảng mã nguồn mở | Loại ở gate cứng OPT §2.1 — không kiểm chứng được cô lập Payment cho PCI-DSS SAQ A (CON-06) mà không sửa sâu lõi |
CON-06 |
Nếu Tech Lead xác nhận kinh nghiệm sâu với một nền tảng cụ thể và POC chứng minh cô lập Payment đạt SAQ A — xét lại cho module không nhạy cảm tài chính (OPT §5) |
| P4 — Serverless-first (Lambda/Step Functions/DynamoDB) | Cold-start Lambda ảnh hưởng DRV-02 (bỏ giỏ) chưa có POC đo trong ngữ cảnh VPC+RDS; chưa có bằng chứng năng lực team serverless-at-scale (CON-05) |
DRV-02, CON-05 |
Nếu có POC đo cold-start đạt yêu cầu và Tech Lead xác nhận năng lực — xét lại cho luồng bất đồng bộ thuần (Notification, Commission batch) như lựa chọn lai, không toàn hệ thống (OPT §5) |
5. Hệ quả
Hệ quả tích cực
- Số đơn vị triển khai cần vận hành/on-call giảm từ ~10 (P1) xuống ~3 (2–3 nhóm monolith +
Payment) — khớp trực tiếp FTE DevOps trung bình thấp (~0,7 FTE,
TCO/hồ sơ thầu) - Effort tới bản chạy được thấp hơn P1 khoảng 70,2 MD (không cần dựng cụm Kafka/MSK)
- Rủi ro công nghệ thấp hơn — managed service phổ biến hơn (RDS, SQS/EventBridge, ECS Fargate)
Hệ quả tiêu cực phải sống chung
- Scale-out độc lập Catalog/Search khỏi Cart/Checkout kém hơn P1 ngay từ ngày một — nếu flash
sale gây tải lệch mạnh giữa Catalog và Cart&Order, cả hai vẫn scale chung trong "Nhóm Giao dịch"
cho tới khi tách (xem
ASR-014/ADR-012) - Nếu
POC-01/POC-02FAIL: phải bổ sung kiến trúc lai (Kafka/MSK riêng cho hot-path đặt hàng, hoặc tách read replica sớm hơn dự kiến) — không quay lại P1 hoàn toàn (OPT §1)
Cái quyết định này khoá lại
| Muốn đổi về sau thì | Tốn |
|---|---|
| Tách toàn bộ modular monolith thành microservices sau go-live | Tái cấu trúc network/DB/CI-CD riêng biệt cho từng module — ước > 4 tuần, có rủi ro downtime khi tách |
| Đổi lại SQS/EventBridge sang Kafka/MSK sau khi đã có producer/consumer thật | Viết lại toàn bộ tầng tích hợp bất đồng bộ — xem ADR-005 (quyết định riêng, không lặp ở đây) |
Việc phát sinh
| Việc | Chủ | Hạn | Ghi ở đâu |
|---|---|---|---|
Chạy POC-01/POC-02 theo tiêu chí PASS/FAIL đã viết trước |
Tech Lead + DevOps/DBA | Trước khi ADR này chuyển Accepted |
ARISK_e-commerce_v1.0.md §6 |
Xác nhận OQ-010 (team thật) |
Tech Lead | Trước khi Accepted |
00-index/OQ_e-commerce.md |
| Thêm fitness function kiểm tra ranh giới module (không cho import chéo giữa domain package) | SA + Tech Lead | GĐ3 (AGD/FIT) |
FIT-01 (ứng viên) |
| Kế hoạch tách Catalog/Search nếu traffic vượt ngưỡng B×2 | Tech Lead | Khi có bằng chứng traffic thật | TDEBT (GĐ3) |
6. Cách kiểm chứng quyết định này được tuân thủ
| Cách kiểm | Công cụ | Chạy ở đâu | FIT |
|---|---|---|---|
| Không có import chéo trực tiếp DB giữa các domain package trong monolith (chỉ qua API nội bộ/event) | dependency-cruiser hoặc ArchUnit-style rule | CI | FIT-01 (ứng viên, GĐ3) |
| Số đơn vị triển khai (ECS service) đúng 2–3 nhóm + 1 Payment, không phình thêm không kiểm soát | Kiểm tra hạ tầng (Terraform plan review) | CI/CD pipeline | FIT-02 (ứng viên) |
POC-01/POC-02 — bài đo throughput/tải |
k6/artillery, load test staging | Trước go-live, lặp lại trước mỗi major release | — (kết quả ghi vào ARISK §6) |
7. Điều kiện xét lại
| Dấu hiệu | Ngưỡng | Ai theo dõi |
|---|---|---|
| Traffic thật tiệm cận kịch bản B × 2 | ~20.000 concurrent user | Tech Lead/SRE |
POC-01 hoặc POC-02 FAIL |
Không đạt tiêu chí PASS đã viết trước (ARISK §6) |
Tech Lead |
| Team thật khác biệt đáng kể so với giả định "team MVP chuẩn" | Số BE thật < 50% giả định DEC-02, hoặc > gấp đôi |
Tech Lead/PM |
8. Tham chiếu
- POC:
ARISK_e-commerce_v1.0.md §6 POC-01, POC-02 - Bài đo: chưa chạy — xem §Điều kiện chuyển Accepted
- Tài liệu ngoài:
OPT_e-commerce_v1.0.md§1, §3, §4, §5 (bảng chấm điểm đầy đủ, không lặp lại) ·SAD_e-commerce_v1.0.md §2, §4(hiện thực hoá quyết định này thành C4 Container) - Thảo luận:
DEC-06(00-index/DEC_e-commerce.md), duyệt từng phần 2026-09-12
9. Review log (không đổi Status)
| Ngày | Người review | Vai trò | Quyết định | Lý do chưa chuyển Accepted |
|---|---|---|---|---|
| 2026-09-15 | Điều phối dự án (thay mặt Tech Lead, chế độ chạy thử) | Tech Lead (ký thay, ngoại lệ DEC-01) |
Reviewed (Proposed giữ nguyên) — nội dung đủ làm cơ sở thiết kế tiếp (icd/dat/sec/inf/fail) |
Chưa có chữ ký thật Tech Lead; POC-01+POC-02 chưa chạy; OQ-010 (team thật) chưa xác nhận |
Đây là ghi nhận review nội dung, không phải "sign" theo nghĩa gate:
Statusgiữ nguyênProposed. Xem00-index/ADL_e-commerce.md(Change Log — Review 2026-09-15) vàADL §8"Việc phải làm" cho điều kiện chuyểnAccepted. Confidence tổng thể của lượt review: 🔴 —AG2chưa ký.