Files
sys-analysis-design/sa-output/e-commerce/02-architecture/adr/ADR-006_chien-luoc-du-lieu-rds-gop-schema-per-module.md
Canhchimlac 343ad8bbbc save
2026-09-15 16:02:30 +07:00

11 KiB

ADR-006 — Một cụm RDS PostgreSQL chính, schema-per-module, chịu tải ghi/đọc gộp (trừ Payment)

Tên file: adr/ADR-006_chien-luoc-du-lieu-rds-gop-schema-per-module.md

Status Proposed (🔴 radar ≥8 — theo decision-radar.md §2/§6, không được chuyển Accepted khi chưa có POC-02 PASS)
Date 2026-09-15
Người quyết SA + Tech Lead/DBA (dữ liệu — decision-radar.md §5)
Người đề xuất SA (qua skill sa-2-architecture, hoạt động adr)
Điểm radar ~8/10 — 🔴 bắt buộc POC trước Accepted
Supersedes —
Superseded by —
Liên quan ASR-006 · QAS-006 · ARISK-02 · POC-02 · ADR-001 · ADR-002 (Payment tách riêng, độc lập)

⚠️ ADR bất biến sau khi Accepted. Muốn đổi quyết định thì viết ADR mới có Supersedes: ADR-006 và đổi trạng thái bản cũ thành Superseded by.


1. Bối cảnh

Modular monolith P2 (ADR-001) cần một chiến lược dữ liệu nhất quán cho mọi module ngoài Payment (đã tách riêng theo ADR-002). ASR-006 ép ra một cụm RDS PostgreSQL Multi-AZ chính, chia theo schema-per-module — chưa đo tải ghi (checkout) + đọc (catalog) gộp ở tải đỉnh flash sale. Đây là quyết định đạt ngưỡng radar ≥8 vì chưa có bài đo thật trong ngữ cảnh này (ASM-08).

Ràng buộc đang chi phối:

Nguồn Nội dung
ASR-006 1 RDS chính schema-per-module, chịu tải ghi/đọc gộp cho mọi module trừ Payment
QAS-006 p95 write (checkout) ≤300ms, p95 read (catalog) ≤200ms, CPU <75%, connection pool không exhaust
ADR-001 Modular monolith P2 — tiền đề cho việc gộp dữ liệu theo schema thay vì database-per-service
ADR-002 Payment có RDS riêng — không nằm trong phạm vi cụm RDS chính này

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
Payment có RDS riêng, tách biệt hoàn toàn khỏi cụm chính 🟢 Đã kiểm chứng ADR-002
1 cụm RDS db.r6g.xlarge Multi-AZ đủ chịu tải ghi/đọc gộp cho các module ngoài Payment ở kịch bản A/B 🔴 Giả định (ASM-08) POC-02 — chưa chạy
Connection pool chia theo module đủ tránh một module chiếm hết pool 🔴 Giả định Chưa có thiết kế connection pool chi tiết — thuộc DAT, hoạt động 5

2. Phương án đã cân nhắc

PA-1 — Database-per-service (mỗi module 1 RDS logic riêng)

Mô tả Mỗi module (Identity, Catalog, Cart & Order, Seller, Commission, Promotion, Review, Notification, Shipping) có 1 RDS instance/logic DB riêng — theo SAD.md/hồ sơ thầu (P1)
Ưu Cô lập tải hoàn toàn — một module quá tải không ảnh hưởng module khác; dễ scale/tune riêng từng DB
Nhược ~9-10 RDS instance phải patch/backup/monitor độc lập — vi phạm Conway với năng lực team hiện tại (CON-05); tăng chi phí vận hành đáng kể so với 1-2 instance
Chi phí đảo ngược Cao — gộp lại thành 1 cụm sau này cần migrate dữ liệu qua nhiều DB, đồng bộ schema

PA-2 — 1 cụm RDS chính, schema-per-module (ranh giới logic, chung instance) (chọn)

Mô tả 1 cụm RDS PostgreSQL Multi-AZ, mỗi module có schema riêng trong cùng instance (ranh giới logic rõ ràng qua schema + quyền truy cập DB user riêng theo schema)
Ưu Ít thành phần phải vận hành hơn (1 instance thay vì ~9-10) — khớp Conway với team hiện tại; vẫn giữ ranh giới logic rõ ràng qua schema (không phải 1 schema dùng chung hỗn loạn)
Nhược Một module quá tải (VD Catalog bị truy vấn nặng mùa flash sale) có thể ảnh hưởng module khác dùng chung instance (Cart & Order, Commission…) — chưa đo tải gộp thật
Chi phí đảo ngược Trung bình-cao — tách read replica/DB riêng cho từng module sau khi đã gộp là một dự án migration riêng

PA-3 — 1 cụm RDS, 1 schema chung (không phân tách theo module)

Mô tả Tất cả bảng của mọi module nằm chung 1 schema, không phân tách quyền truy cập theo module
Ưu Đơn giản nhất về mặt cấu hình DB ban đầu
Nhược Không có ranh giới logic nào giữa các module — vi phạm D7 ("mỗi thực thể có đúng một chủ sở hữu" cần ranh giới rõ để enforce); dễ phát sinh coupling ngầm (module A viết trực tiếp bảng của module B) làm mất tác dụng modular monolith
Chi phí đảo ngược Cao — tách schema sau khi code đã coupling chéo là công việc tái cấu trúc lớn

Bảng so sánh

Tiêu chí PA-1 (DB-per-service) PA-2 (1 cụm, schema-per-module) PA-3 (1 cụm, 1 schema)
Số thành phần phải vận hành ~9-10 1 1
Cô lập tải giữa module ✅ Hoàn toàn 🟠 Một phần (chung instance) ❌ Không
Ranh giới logic rõ ràng (D7) ✅ ✅ (qua schema) ❌
Khớp Conway (CON-05) ❌ ✅ ✅

3. Quyết định

Chọn PA-2 — 1 cụm RDS PostgreSQL Multi-AZ chính, schema-per-module, cho mọi module ngoại trừ Payment.

Vì sao: Cân bằng giữa khớp Conway (CON-05, ít thành phần vận hành hơn database-per-service) và vẫn giữ ranh giới logic rõ ràng qua schema (khác PA-3 gộp chung 1 schema mất kiểm soát ranh giới dữ liệu).

Phạm vi áp dụng: Toàn bộ module ngoại trừ Payment (đã có RDS riêng theo ADR-002).

Đ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-02 PASS — p95 write ≤300ms, p95 read ≤200ms, CPU <75%, connection pool không exhaust Tech Lead/DBA 🔴 Chưa chạy (ARISK-02)
Thiết kế connection pool theo module (giới hạn để tránh một module chiếm hết pool) Tech Lead/DBA Chưa thiết kế — thuộc DAT

🔴 Bắt buộc theo decision-radar.md §2/§6 — điểm radar ~8 (≥8) đồng nghĩa ADR này không được chuyển Accepted cho tới khi POC-02 chạy xong và PASS. Nếu POC-02 FAIL: tách read replica/DB riêng cho Catalog/Search sớm hơn dự kiến, cập nhật TCO (chi phí hạ tầng tăng, tiệm cận P1 cho phần đó — đã cảnh báo ở TCO §3.3).

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
PA-1 — Database-per-service Vi phạm Conway với năng lực team hiện tại; tăng chi phí vận hành đáng kể CON-05, OPT §4 tiêu chí 5 Nếu POC-02 FAIL nghiêm trọng (không thể khắc phục bằng read replica) và team đủ lớn để vận hành nhiều DB — xét lại cho riêng module gây nghẽn (VD tách Catalog)
PA-3 — 1 cụm, 1 schema chung Không có ranh giới logic — vi phạm D7, dễ coupling chéo giữa module D7 (design-rules) Không xét lại — đây là anti-pattern cho modular monolith, không phải trade-off hợp lý

5. Hệ quả

Hệ quả tích cực

  • Chỉ 1 RDS instance chính phải patch/backup/monitor (ngoài Payment) — khớp năng lực team, giảm chi phí vận hành đáng kể so với database-per-service
  • Ranh giới logic rõ ràng qua schema — enforce được D7 (mỗi thực thể có đúng một chủ)

Hệ quả tiêu cực phải sống chung

  • Một module quá tải (VD Catalog mùa flash sale) có thể ảnh hưởng module khác dùng chung instance — cần connection pool giới hạn theo module để giảm thiểu
  • Nếu POC-02 FAIL, phải tách read replica sớm hơn dự kiến — tăng chi phí hạ tầng ngoài kế hoạch ban đầu

Cái quyết định này khoá lại

Muốn đổi về sau thì Tốn
Tách một module ra RDS riêng sau khi đã gộp Migration dữ liệu + đồng bộ song song trong thời gian chuyển đổi — dự án riêng, không miễn phí

Việc phát sinh

Việc Chủ Hạn Ghi ở đâu
Chạy POC-02 theo tiêu chí đã viết trước Tech Lead/DBA Trước khi Accepted ARISK_e-commerce_v1.0.md §6
Thiết kế connection pool giới hạn theo module SA (hoạt động dat) + DBA GĐ2 tiếp theo DAT_e-commerce
Kế hoạch tách read replica dự phòng nếu POC-02 FAIL Tech Lead/DBA Khi có kết quả POC-02 TDEBT (GĐ3) hoặc cập nhật TCO

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
POC-02 — tải ghi/đọc gộp Load test staging, cấu hình instance thật Trước Accepted, lặp lại trước mỗi major release — (ghi vào ARISK §6)
Không có bảng nào bị truy cập chéo schema (module A viết trực tiếp bảng module B) DB user permission theo schema + code review/lint CI (schema access lint) FIT-09 (ứng viên)
CPU/connection pool RDS trong ngưỡng ở production CloudWatch metric + alarm Production, liên tục —

7. Điều kiện xét lại

Dấu hiệu Ngưỡng Ai theo dõi
POC-02 FAIL Không đạt tiêu chí PASS đã viết trước Tech Lead/DBA
CPU RDS production vượt 75% thường xuyên > 3 lần/tuần trong giờ cao điểm SRE
Connection pool exhaust trong production Bất kỳ lần nào SRE

8. Tham chiếu

  • POC: ARISK_e-commerce_v1.0.md §6 POC-02
  • Bài đo: FIT-09 (ứng viên GĐ3)
  • Tài liệu ngoài: QAS_e-commerce_v1.0.md §A3 QAS-006
  • Thảo luận: ASR_e-commerce_v1.0.md §B2 ASR-006, OPT_e-commerce_v1.0.md §8 ASM-08

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) Radar 8 — bắt buộc POC-02 (tải RDS gộp) PASS trước khi Accepted; chưa chạy

Đây là ghi nhận review nội dung, không phải "sign" theo nghĩa gate: Status giữ nguyên Proposed. Xem 00-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ển Accepted. Confidence tổng thể của lượt review: 🔴 — AG2 chưa ký.