Giai đoạn 1 — Monolith + PostgreSQL

Bối cảnh VietShop ngày 0: 3 founder (2 dev), vốn đủ sống 12 tháng, mục tiêu ra thị trường trong 2 tháng. FR: đăng ký/đăng nhập, danh mục sản phẩm, giỏ hàng, đặt hàng COD, quản trị đơn giản. NFR thật sự chỉ có hai: ra tính năng nhanh và không mất dữ liệu đơn hàng. 1. Vấn đề cần giải Không phải scale — là tồn tại. Xác suất sản phẩm chết vì không có user cao gấp trăm lần chết vì quá nhiều user. Kiến trúc phù hợp là kiến trúc tối đa hóa tốc độ học từ thị trường trên mỗi đồng vốn. ...

July 13, 2026 · 4 min

Phần 12 — System Design Evolution

Chương quan trọng nhất của tài liệu. Mọi khái niệm ở các phần trước được đặt vào một câu chuyện duy nhất, kể từ đầu đến cuối. Hệ thống xuyên suốt: sàn E-commerce “VietShop” Chúng ta theo chân một sàn thương mại điện tử Việt Nam từ ngày đầu tiên đến khi phục vụ hàng chục triệu người dùng. Chọn e-commerce vì nó chứa đủ các bài toán kinh điển: read-heavy (duyệt sản phẩm), tranh chấp ghi (tồn kho), tiền bạc (không được sai), spike cực đoan (flash sale), tác vụ nền (email, ảnh), tìm kiếm, và báo cáo. ...

July 13, 2026 · 3 min

11.3. Biên phòng thủ — API Gateway, Rate Limiting, WAF

1. Problem Statement Internet là môi trường thù địch mặc định: bot chiếm phần lớn traffic của nhiều site, credential stuffing chạy 24/7, scraper hút catalog, và thi thoảng một chiến dịch DDoS thật sự. Nếu mỗi service tự xử lý các mối lo này, ta có N bản cài đặt lệch nhau của cùng các phòng thủ (11.1 §2 — cùng lý do tập trung AuthN). Biên (edge) tồn tại để gom các mối quan tâm cắt ngang về một tuyến phòng thủ có tầng — để service phía sau tập trung vào nghiệp vụ, và để “một chỗ vá” khi có chuyện. ...

July 13, 2026 · 7 min

11.2. OAuth2, OIDC & JWT — ủy quyền và token trong hệ phân tán

1. Problem Statement Ba bài toán token của mọi hệ hiện đại: app bên thứ ba cần truy cập dữ liệu user mà không cầm mật khẩu của user (ủy quyền — OAuth2); nhiều ứng dụng cần cùng một đăng nhập (SSO — OIDC); và N service cần xác minh danh tính người gọi mà không gọi về trung tâm mỗi request (token tự xác minh — JWT). Ba bài, một họ chuẩn — và một bãi mìn thuật ngữ nơi “dùng JWT” và “dùng OAuth” bị nói như thể là quyết định một chữ, trong khi mỗi lựa chọn con bên trong (flow nào, token sống bao lâu, thu hồi thế nào) mới là nơi an toàn được quyết định. ...

July 13, 2026 · 7 min

11.1. Authentication & Authorization — bạn là ai, bạn được làm gì

1. Problem Statement Mọi request chạm hệ thống phải được trả lời hai câu khác nhau về bản chất: bạn là ai (Authentication — xác thực danh tính) và bạn được làm gì (Authorization — kiểm tra quyền). Trộn hai câu này — hoặc trả lời câu hai bằng niềm tin “đã qua cửa là được tất” — là gốc của lớp lỗ hổng phổ biến và tàn phá nhất trong thực tế: broken access control (nhiều năm liền đứng đầu OWASP Top 10), mà điển hình là IDOR — user A đổi order_id trên URL và đọc được đơn của user B, vì hệ chỉ hỏi “đã đăng nhập chưa” mà quên hỏi “đơn này của ai”. ...

July 13, 2026 · 6 min

Phần 11 — Security

Chủ đề: Authentication, Authorization, OAuth2, JWT, Rate Limiting, WAF, API Gateway. Luận điểm trung tâm của phần này Security là thuộc tính kiến trúc, không phải tính năng gắn sau — và giống durability (1.1 §9), lỗi của nó không sửa được bằng refactor: dữ liệu đã rò là đã rò. Ba nguyên tắc gốc chi phối mọi chương: Defense in depth: nhiều lớp, không lớp nào được tin là đủ — kẻ tấn công phải vượt tất cả, còn bạn chỉ cần một lớp bắt được. Least privilege: mọi thành phần (người, service, token) chỉ có quyền tối thiểu cho việc của nó — blast radius của một credential bị lộ tỷ lệ thuận với quyền nó mang. Không tự chế crypto/auth: dùng chuẩn đã được soi (OAuth2/OIDC, JWT ký chuẩn, thư viện đã kiểm toán) — sáng tạo trong security là sáng tạo cách thua. Mục lục 11.1. Authentication & Authorization — bạn là ai, bạn được làm gì 11.2. OAuth2, OIDC & JWT — ủy quyền và token trong hệ phân tán 11.3. Biên phòng thủ — API Gateway, Rate Limiting, WAF Bản đồ security trong toàn tài liệu Mảnh Ở đâu Compliance là NFR (Nghị định 13, PCI-DSS) 1.1 §3.2 Che PII trong log/tín hiệu 10.1 §3, 10.2 §6 Backup mã hóa, immutable, chống ransomware 3.2 ACL cho topic/queue — ai được phát/nghe 6.5 §6 Idempotency chống replay nghiệp vụ 13.3 Rate limiting như công cụ reliability 13.1 — thundering herd Phần này đứng ở góc kiến trúc sư hệ backend — identity, token, và biên — không thay thế được chuyên môn AppSec/PenTest; nó bảo đảm phần thiết kế không tạo ra những lỗ mà không PenTest nào vá nổi. ...

July 13, 2026 · 2 min

10.3. Dashboard, Alerting & On-call — từ tín hiệu đến con người

1. Problem Statement Tín hiệu hoàn hảo (10.1) chảy qua pipeline chuẩn (10.2) vẫn chưa cứu được ai — khâu cuối là con người ra quyết định dưới áp lực lúc 3h sáng. Khâu này hỏng theo hai cách đối xứng: alert quá nhiều (người trực tê liệt, tắt thông báo, bỏ lỡ cái thật — alert fatigue là nguyên nhân gốc của nhiều sự cố kéo dài hơn là thiếu monitoring) và alert quá ít/quá trễ (khách hàng là người phát hiện sự cố). Thiết kế giao diện máy–người này là một bài thiết kế hệ thống đúng nghĩa — có SLO, có failure mode, có evolution. ...

July 13, 2026 · 7 min

10.2. OpenTelemetry & pipeline tín hiệu — thu, xử lý, lưu, trả tiền

1. Problem Statement Ba trụ (10.1) sinh ra một dòng dữ liệu khổng lồ chảy liên tục từ mọi process — và ba câu hỏi hạ tầng: thu bằng chuẩn nào (để không viết lại instrumentation khi đổi backend), vận chuyển và xử lý ở đâu (lọc, sample, làm giàu, che nhạy cảm — trước khi trả tiền lưu), lưu vào đâu với chi phí nào. Trả lời tùy hứng ba câu này là cách các công ty tỉnh dậy với hóa đơn observability ngang hóa đơn compute và một mớ agent chồng chéo không ai dám tắt. ...

July 13, 2026 · 6 min

10.1. Ba trụ — Logging, Metrics, Tracing

1. Problem Statement 2h37 sáng, alert: “checkout error budget đang cháy”. Người trực cần trả lời ba câu theo thứ tự: có chuyện gì / ở đâu (metrics — 30 giây), chặng nào trong chuỗi 8 service (trace — 2 phút), chính xác chuyện gì đã xảy ra ở chặng đó (logs — 5 phút). Thiếu trụ nào, thời gian ở bước đó nhân 10 — MTTR là hàm trực tiếp của chất lượng ba trụ (3.1 §5 — MTTR quan trọng hơn MTBF). Chương này mổ cấu trúc từng trụ và cách chúng nối vào nhau — vì ba trụ rời rạc chỉ là ba đống dữ liệu. ...

July 13, 2026 · 7 min

Phần 10 — Observability

Chủ đề: Logging, Metrics, Tracing, OpenTelemetry, Dashboard, Alerting. Luận điểm trung tâm của phần này Observability là khả năng trả lời câu hỏi chưa biết trước về hệ thống từ tín hiệu nó phát ra — khác monitoring (canh các câu hỏi đã biết). Trong hệ phân tán, nó không phải tiện nghi mà là điều kiện vận hành: toàn bộ Phần 13 — mọi mục Metric/Dashboard/Alert/Điều tra — chính là phần này trong hành động. ...

July 13, 2026 · 2 min

9.3. Lựa chọn công nghệ search — khung quyết định

1. Problem Statement “Cần search” không tự động nghĩa là “cần Elasticsearch”. Phổ lựa chọn trải từ một câu tsvector trong DB đang có, đến cụm phân tán nhiều node với nghề vận hành riêng — chênh nhau hai bậc độ lớn về chi phí trọn đời. Chọn theo thói quen (“ai cũng dùng ES”) hoặc theo sợ hãi (“PG sao làm search được”) đều bỏ qua câu hỏi đúng: workload này cần gì, và mức khiêm tốn nhất đáp ứng được là gì (5.7 §2 — cửa kiểm tra câu 3). ...

July 13, 2026 · 5 min

9.2. Kiến trúc hệ search hoàn chỉnh — indexing pipeline, query side, vận hành

1. Problem Statement Engine tốt + analyzer tốt (9.1) chưa thành hệ search: còn phải trả lời — dữ liệu từ nguồn sự thật đến index bằng đường nào, trễ bao nhiêu, sót thì sao? Autocomplete, facet, filter — mỗi thứ cần cấu trúc gì? Reindex 50 triệu document giữa production như thế nào? Đây là phần “hệ thống” của search — nơi các bài học outbox, projection, backlog của toàn tài liệu hội tụ vào một use case. ...

July 13, 2026 · 6 min

9.1. Full-text Search — nguyên lý: inverted index, analyzer, relevance

1. Problem Statement User gõ ao khoac nam gia re; kho có 2 triệu sản phẩm. Yêu cầu: kết quả liên quan trả trong < 100ms, khớp được dù thiếu dấu, sai chính tả nhẹ, đảo trật tự từ; và “liên quan” phải gần với “thứ user muốn mua” chứ không chỉ “chuỗi giống nhau”. LIKE '%áo khoác%' thất bại toàn tập: quét toàn bảng (không index nào giúp wildcard hai đầu), yêu cầu khớp chuỗi liên tục (đảo từ là mất), không hiểu dấu, và không có khái niệm xếp hạng. Cần một cấu trúc dữ liệu và một bộ máy ngôn ngữ sinh ra cho đúng bài này. ...

July 13, 2026 · 7 min

Phần 9 — Search

Chủ đề: Full-text Search, Elasticsearch, OpenSearch — và kiến trúc của một hệ search hoàn chỉnh. Luận điểm trung tâm của phần này Search tồn tại vì một khoảng trống cấu trúc: B-tree trả lời “bằng/trong khoảng”, columnar trả lời “tổng theo nhóm” — không cấu trúc nào trả lời “chứa khái niệm X, xếp theo độ liên quan” (5.7 §1 — bảng quyết định gốc). Và một sự thật nghiệp vụ: với e-commerce/marketplace/content, search là cỗ máy doanh thu — khác biệt giữa search tốt và tồi đo được bằng conversion, không phải bằng ms. ...

July 13, 2026 · 2 min

8.3. Resharding & vận hành hệ đã shard

1. Problem Statement Mọi quyết định sharding đều sai dần theo thời gian: dữ liệu tăng 10× (4 shard thành chật), phân bố lệch dần (một shard 80% đầy trong khi anh em 30%), tenant VIP phình vượt shard của nó, hoặc — đau nhất — shard key hóa ra chọn sai (8.1 §3.2). Câu hỏi của chương này: làm sao thay đổi cách chia dữ liệu trên hệ đang chạy, không downtime, không mất ghi — bài toán được xếp vào loại khó nhất của vận hành dữ liệu, và là lý do người ta nói “shard key là cam kết hôn nhân”. ...

July 13, 2026 · 7 min

8.2. Consistent Hashing — thêm bớt node mà không xáo cả thế giới

1. Problem Statement Hash sharding ngây thơ: node = hash(key) mod N. Đẹp cho đến ngày N đổi. Thêm node thứ 5 vào cụm 4 node: mod 4 → mod 5 — ~80% key đổi chỗ. Với cache: 80% miss đồng loạt = tự gây avalanche (13.1); với storage: di chuyển 80% dữ liệu qua mạng chỉ để thêm một máy. Mà thêm/bớt node là chuyện thường kỳ: scale theo tải, node chết, bảo trì. Cần một cách ánh xạ key → node sao cho N đổi thì chỉ ~1/N key phải dời chỗ — mức tối thiểu lý thuyết (dữ liệu phải sang node mới thì mới có ích). ...

July 13, 2026 · 6 min

8.1. Partitioning & Sharding — chia dữ liệu và cái giá của shard key

1. Problem Statement Bảng orders của VietShop sau 4 năm: 3TB, 5 tỷ hàng. Ba loại đau cùng lúc: quản trị (backup 6 giờ, tạo index 2 ngày, xóa dữ liệu cũ bằng DELETE là bão bloat — 5.1); hiệu năng (index sâu hơn, working set vượt RAM, vacuum lê lết); và cuối cùng — trần vật lý (một máy hết cỡ để scale-up, ghi vượt năng lực single-writer — 4.2). Ba loại đau, hai lời giải khác cấp độ: partitioning trong node cho hai loại đầu, sharding ra nhiều node cho loại thứ ba. Nhầm cấp độ — sharding khi chỉ cần partition — là mua độ phức tạp lớn nhất trong nghề để chữa bệnh có thuốc rẻ. ...

July 13, 2026 · 7 min

Phần 8 — Data Partitioning

Chủ đề: Partitioning, Sharding, Consistent Hashing, phối hợp với Replication — và bài toán khó nhất: resharding hệ đang chạy. Luận điểm trung tâm của phần này Partitioning là câu trả lời cho câu hỏi cuối cùng của scale: khi một node không chứa nổi / phục vụ nổi toàn bộ dữ liệu thì sao? Chia dữ liệu ra N node — nhưng cái giá là mất những gì “một node” cho không: transaction toàn cục, join tùy tiện, thứ tự toàn cục, và sự đơn giản. Vì thế nguyên tắc số một, nhắc lại từ 1.5: sharding là phương án cuối, sau khi index/cache/replica/scale-up đã hết bài — và là phương án gần như không có đường lùi. ...

July 13, 2026 · 2 min

7.3. Distributed Cache — cache khi một node không đủ

1. Problem Statement Một node Redis phục vụ ~100K ops/s và chứa được RAM của một máy (5.4). Hệ lớn vượt cả hai trần: cần triệu ops/s, cần cache working set hàng trăm GB, và cần cache sống sót khi node chết (vì mất cache = avalanche, 13.1 — với hệ hit-rate 95%, cache không còn là “tùy chọn hiệu năng” mà là thành phần sống còn). Distributed cache = chia key ra nhiều node + nhân bản — và ngay lập tức thừa hưởng mọi bài toán của Phần 4 và Phần 8: partition, hot key, rebalance, consistency giữa các tầng. ...

July 13, 2026 · 7 min

7.2. Cache Invalidation — bài toán khó thứ nhất của khoa học máy tính

“There are only two hard things in Computer Science: cache invalidation and naming things.” — câu đùa sống lâu vì nó đúng. Chương này giải thích vì sao nó khó về nguyên lý, và bộ công cụ thực dụng để sống chung. 1. Problem Statement Nguồn sự thật thay đổi; bản sao trong cache thành nói dối. Câu hỏi: làm bản sao hết nói dối đúng lúc (đủ tươi cho nghiệp vụ) với chi phí chịu được (không biến mỗi thao tác ghi thành chiến dịch truy quét N tầng cache). Hai đầu của phổ đều dễ: không bao giờ invalidate (cache tĩnh vĩnh viễn) và invalidate mọi thứ mỗi lần ghi (tương đương không có cache). Mọi hệ thật nằm giữa — và khoảng giữa là nơi ở của race condition. ...

July 13, 2026 · 8 min

7.1. Bốn chiến lược cache — ai ghi, ai đọc, ai chịu trách nhiệm

1. Problem Statement “Thêm cache” nghe như một quyết định — thực ra là bốn quyết định độc lập: khi miss thì ai đi lấy dữ liệu (app hay cache)? Khi ghi thì cache được cập nhật lúc nào (cùng lúc, sau, hay không bao giờ)? Ghi có chờ DB không? Và ai chịu trách nhiệm khi hai bên lệch nhau? Bốn chiến lược kinh điển là bốn tổ hợp câu trả lời — chọn sai tổ hợp cho workload là nguồn của cả bug consistency lẫn hiệu năng tồi. ...

July 13, 2026 · 6 min

Phần 7 — Caching

Chủ đề: Cache Aside, Read Through, Write Through, Write Back, Cache Invalidation, Distributed Cache. Luận điểm trung tâm của phần này Cache tồn tại vì hai sự thật: RAM nhanh hơn disk ~1000 lần (chương 00 §3), và truy cập dữ liệu có locality — một phần nhỏ dữ liệu nhận phần lớn truy cập (luật lũy thừa, 13.2 — hot partition là mặt tối của cùng quy luật). Không có locality, cache vô dụng; có locality, cache là đòn bẩy hiệu năng rẻ nhất trong toàn bộ hộp đồ nghề. ...

July 13, 2026 · 2 min

6.8. Outbox Pattern — móng của mọi event đáng tin

1. Problem Statement Một thao tác nghiệp vụ cần làm hai việc trên hai hệ thống: ghi trạng thái vào database và thông báo ra ngoài (publish event lên Kafka, enqueue job, gọi webhook). Code ngây thơ: db.commit(order) // việc 1: thành công kafka.publish(event) // việc 2: ...crash ở đây thì sao?Crash giữa hai dòng → hệ thống nói dối: đơn tồn tại trong DB nhưng thế giới không bao giờ biết — không email, không trừ kho, không analytics. Đảo thứ tự thì dối chiều ngược lại: event bay đi cho đơn chưa từng commit. Đây là dual-write problem — và nó không hiếm: nó xảy ra mỗi lần deploy restart process đúng khoảnh khắc đó, mỗi lần Kafka chập chờn đúng lúc DB đã commit. Không thể fix bằng try/catch hay retry — vấn đề là hai hệ thống không có transaction chung, về nguyên lý (4.4 — không có atomic commit giữa hai hệ tự trị rẻ tiền). ...

July 13, 2026 · 8 min

6.7. Saga — transaction khi không còn transaction

1. Problem Statement Đặt hàng chạm ba service, ba database: Orders (tạo đơn), Inventory (trừ kho), Payments (trừ tiền). Trong monolith, đây là một transaction ACID — ba thao tác cùng thành công hoặc cùng biến mất, miễn phí (12.1). Tách service xong (12.6), ACID xuyên ranh giới không còn tồn tại: kho trừ rồi, tiền fail — ai trả kho về? Hệ thống kẹt ở trạng thái nửa vời mà không cơ chế nào tự dọn. ...

July 13, 2026 · 9 min

6.6. Event-driven Architecture — nghĩ bằng sự kiện

Kafka (6.5) là công cụ; event-driven là cách nghĩ. Chương này về cách nghĩ — phần khó hơn và ít được dạy hơn. 1. Problem Statement Hệ nhiều service trưởng thành đối mặt một mâu thuẫn: nghiệp vụ đòi phản ứng dây chuyền (đơn tạo → trừ kho, cộng điểm, gửi mail, tính hoa hồng, cảnh báo fraud…) trong khi kiến trúc đòi các phần không dính nhau. Orchestration bằng lời gọi trực tiếp thỏa vế một, phá vế hai: service “đầu chuỗi” phải biết và sống chết cùng mọi service cuối chuỗi (12.7 §1). Event-driven giải mâu thuẫn bằng cách đảo chủ ngữ: thay vì A bảo B làm, A công bố điều đã xảy ra; B tự quyết định phản ứng. ...

July 13, 2026 · 8 min

6.5. Kafka — distributed log cho sự kiện

Vì-sao-tồn-tại và hành trình áp dụng đã kể ở 12.7. Chương này mổ nội thất: vì sao log lại nhanh đến thế, các đảm bảo thật sự của Kafka nằm ở đâu, và giá vận hành của chúng. 1. Problem Statement Cần một nơi công bố sự thật đã xảy ra (order created, payment captured, price changed) sao cho: nhiều hệ tiêu thụ độc lập theo nhịp riêng, hệ đến sau đọc lại được lịch sử, thứ tự trong phạm vi cần thiết được giữ, throughput hàng trăm nghìn–triệu event/giây, và dữ liệu không mất khi máy chết. Không mô hình queue nào thỏa đồng thời các yêu cầu này — cần một mô hình khác: append-only log phân tán. ...

July 13, 2026 · 8 min

6.4. RabbitMQ — smart broker cho work queue

Bối cảnh vì-sao-tồn-tại và hành trình đưa nó vào hệ thống đã kể ở 12.4. Chương này đi sâu vào nội thất, mô hình vận hành và ranh giới của nó. 1. Problem Statement Cần giao việc một cách tin cậy: mỗi việc đến đúng một worker, việc fail được thử lại, việc hỏng vĩnh viễn được cách ly có địa chỉ (DLQ), việc gấp vượt việc thường, spike được hấp thụ. Đây là bài toán task distribution — khác về bản chất với bài toán event distribution (Kafka, 6.5): việc thì tiêu thụ xong là xong, sự kiện thì nhiều bên cùng đọc và có thể đọc lại. ...

July 13, 2026 · 7 min

6.3. gRPC — RPC có kỷ luật cho nội bộ

1. Problem Statement Bên trong một hệ microservices (12.6), các service gọi nhau hàng chục nghìn lần mỗi giây. Ở tần suất đó, những thứ vặt vãnh của REST/JSON thành hóa đơn lớn: serialize/parse JSON ngốn CPU thật (đo được hàng chục % CPU của service nhỏ), payload text phình băng thông, HTTP/1.1 mở nhiều connection và nghẽn head-of-line, và — đắt nhất — hợp đồng lỏng lẻo: field đổi tên, kiểu đổi, chỉ phát hiện lúc runtime bằng sự cố. Hai đầu dây đều là code của bạn; cái bạn cần không phải “phổ cập” mà là contract chặt kiểm tra lúc compile + hiệu năng + streaming — đó là gRPC. ...

July 13, 2026 · 7 min

6.2. GraphQL — client tự khai hình dữ liệu

1. Problem Statement Ứng dụng có nhiều loại client (web, iOS, Android, smart TV, đối tác) trên cùng một domain phức tạp. Với REST thuần, mỗi màn hình gặp một trong hai bệnh: under-fetch (cần 5 resource = 5 round-trip nối tiếp — chết vì latency trên mobile 3G) hoặc over-fetch (endpoint trả 60 field, màn hình dùng 4 — chết vì băng thông). Team backend bị kẹp giữa: hoặc viết endpoint riêng cho từng màn hình của từng client (bùng nổ endpoint), hoặc bắt client chịu. GraphQL đảo quyền: schema thống nhất phía server, client tự khai chính xác hình dữ liệu nó cần, nhận về đúng hình đó trong một round-trip. ...

July 13, 2026 · 7 min

6.1. REST — hợp đồng chung của web

1. Problem Statement Hai hệ thống của hai team (hoặc hai công ty) cần nói chuyện với nhau qua network, và hợp đồng giữa họ phải: dễ hiểu với người mới, dễ debug bằng công cụ phổ thông, tận dụng được hạ tầng web sẵn có (cache, proxy, LB, CDN), và sống sót qua nhiều năm tiến hóa mà không phá client cũ. REST không phải giao thức “tốt nhất” theo bất kỳ trục kỹ thuật đơn lẻ nào — nó là hợp đồng có hệ sinh thái lớn nhất và chi phí gia nhập thấp nhất, và đó chính là giá trị kiến trúc của nó. ...

July 13, 2026 · 7 min