15 đánh đổi kiến trúc hệ thống15 system design trade-offs
Phân tán không cho bạn thứ tốt hơn. Nó cho bạn quyền chọn thứ mình chịu mất.Distribution doesn’t hand you something better. It hands you the right to choose what you lose.
Mười lăm quyết định. Không cái nào có đáp án đúng tuyệt đối — đáp án chỉ tồn tại khi gắn với một con số tải, một ngân sách và một đội ngũ cụ thể.Fifteen decisions. None has a universally correct answer — an answer only exists attached to a specific load number, budget and team.
Chọn cái nàoWhich one to pick
Phần này là thứ bạn dùng hằng ngày. Phần tra cứu chi tiết nằm phía dưới.This is the part you use daily. The detailed reference sits below.
Trước hết: khi nào bạn không cần bất kỳ mục nào ở dướiFirst: when you need none of the fifteen
Baseline rẻ nhất là một cơ sở dữ liệu quan hệ, một ứng dụng đơn khối trên hai instance sau load balancer, session trong Redis hoặc cookie đã ký, sao lưu tự động có kiểm tra khôi phục, và một replica đọc. Một node PostgreSQL phổ thông xử lý thoải mái vài nghìn giao dịch ghi mỗi giây và hàng chục nghìn lượt đọc khi dữ liệu nóng vừa RAM. Phần lớn sản phẩm chết vì không ai dùng, chứ không chết vì hết khả năng mở rộng.The cheapest baseline is one relational database, one monolith on two instances behind a load balancer, sessions in Redis or a signed cookie, automated backups with restore tests, and one read replica. A single ordinary PostgreSQL node comfortably handles a few thousand write transactions per second and tens of thousands of reads when the hot set fits in RAM. Most products die from nobody using them, not from running out of scale.
Bốn tín hiệu cho phép bạn rời baseline — tất cả đều là số đo, không phải linh cảm:Four signals that let you leave the baseline — all measurements, never hunches:
p95 của một endpoint quan trọng vượt SLO nhiều ngày liên tục, và nút thắt nằm ở hạ tầng chứ không phải một index thiếu.
Dữ liệu nóng vượt RAM của node lớn nhất nhà cung cấp bán, hoặc dung lượng vượt đĩa lớn nhất.
CPU hoặc IOPS của node ghi duy trì trên 70% ở giờ bình thường, không phải giờ cao điểm hiếm.
Một sự cố có thật đã gây thiệt hại lớn hơn chi phí của phương án dự phòng.
p95 on an important endpoint has been over its SLO for days, and the bottleneck is infrastructure rather than a missing index.
The hot set exceeds the RAM of the largest node your provider sells, or volume exceeds the largest disk.
CPU or IOPS on the write node stays above 70% during ordinary hours, not just a rare spike.
A real incident has already cost more than the mitigation would.
Bạn có số đo thật (p95, QPS, dung lượng, hoá đơn) không?
│
├─ KHÔNG ──> Dừng. Về baseline. Gắn đo đạc. Quay lại sau 2 tuần.
│
└─ CÓ ──> Nút thắt nằm ở đâu?
│
├─ ĐỌC chậm
│ ├─ Chịu được dữ liệu cũ vài giây? ──> Cache (09) ──> Replica đọc (12)
│ └─ Phải mới tuyệt đối? ──> Đọc từ leader (06) + sửa index (08)
│
├─ GHI chậm
│ ├─ Đỉnh tải ngắn, việc hoãn được? ──> Hàng đợi async (11) + gom lô (13)
│ ├─ Một node đã chạm trần? ──> Partition theo khoá (12)
│ └─ Ghi bị index làm chậm? ──> Bớt index / chọn LSM (08)
│
├─ DUNG LƯỢNG vượt trần ──> Partition (12) + tách dữ liệu lạnh
│
├─ SẬP quá thường
│ ├─ Mất do node chết? ──> Stateless (14) + N+1 (15)
│ ├─ Mất do một AZ chết? ──> Trải nhiều AZ (15)
│ └─ Mất do phụ thuộc chéo? ──> Async (11) + timeout + circuit breaker
│
├─ CHI PHÍ quá cao ──> Hạ dự phòng theo tier (15) + pull thưa hơn (10)
│ + chuyển stream về batch nơi không cần realtime (13)
│
└─ ĐỘI NGŨ đi chậm ──> KHÔNG phải microservices (05). Tách module
trong monolith trước; tách tiến trình chỉ khi
ranh giới đã ổn định 6 tháng và có đội sở hữu.
Do you have real measurements (p95, QPS, volume, the bill)?
│
├─ NO ──> Stop. Go back to baseline. Add instrumentation. Return in 2 weeks.
│
└─ YES ──> Where is the bottleneck?
│
├─ READS are slow
│ ├─ Seconds-old data acceptable? ──> Cache (09) ──> Read replicas (12)
│ └─ Must be absolutely current? ──> Read from leader (06) + fix indexes (08)
│
├─ WRITES are slow
│ ├─ Short spikes, deferrable? ──> Async queue (11) + batching (13)
│ ├─ One node at its ceiling? ──> Partition by key (12)
│ └─ Indexes slowing writes? ──> Drop indexes / pick LSM (08)
│
├─ VOLUME past the ceiling ──> Partition (12) + move cold data out
│
├─ OUTAGES too frequent
│ ├─ A node death kills it? ──> Stateless (14) + N+1 (15)
│ ├─ An AZ loss kills it? ──> Spread across AZs (15)
│ └─ A dependency drags you? ──> Async (11) + timeouts + circuit breakers
│
├─ COST too high ──> Tier redundancy down (15) + poll less often (10)
│ + move non-realtime streams back to batch (13)
│
└─ THE TEAM is slow ──> This is NOT microservices (05). Split modules
inside the monolith first; split processes only
after a boundary is 6 months stable and owned.
Một nguyên tắc cắt ngang: chọn phương án dễ hoàn tác trước. Cache, replica đọc và hàng đợi tháo ra trong một ngày; khoá phân mảnh, ranh giới service và mô hình nhất quán thì không.One rule cuts across all of it: prefer what is easy to undo. Caches, read replicas and queues come out in a day; partition keys, service boundaries and consistency models do not.
Mười lăm đánh đổiThe fifteen
Màu viền cho biết nhóm. Câu đánh đổi được tách riêng khỏi phần “mất” — hạn chế là khuyết tật bạn chịu đựng, đánh đổi là cái giá bạn cố tình trả.The edge colour marks the family. The trade-off line sits apart from what you pay — a limitation is a defect you endure, a trade-off is a price you choose.
01
Consistency vs Availability
Nhất quán dữ liệuData consistency
Phân vùng mạng buộc bạn chọn.Partitions make you choose.
Khi mạng chia cắt, một bên hoặc trả lời đúng, hoặc trả lời được — không thể cả hai, vì bên bị cô lập không có cách nào biết bên kia vừa ghi gì.When the network splits, a side either answers correctly or answers at all — never both, because the isolated side cannot learn what the other just wrote.
Dùng khiUse it when
Chọn CP: số dư, tồn kho vé, hạn mức tín dụng, khoá phân tán
Pick per business flow, never for the whole system
ĐượcYou get
CP xoá hẳn lớp lỗi bán quá số lượng
AP sống sót khi mất một phần ba số node
CP eliminates the oversold-inventory bug class
AP survives losing a third of its nodes
MấtYou pay
CP có thể ngừng phục vụ dù mọi node đều khoẻ
AP đẩy việc hoà giải xung đột lên tầng ứng dụng
CP can stop serving while every node is healthy
AP pushes conflict reconciliation into your code
Đánh đổiThe trade-offChọn CP là đổi khả năng trả lời trong lúc mạng chia cắt để lấy lời hứa không bao giờ đưa ra một đáp án sai.Choosing CP trades the ability to answer during a partition for the promise of never returning a wrong answer.
Dấu hiệu nhận biếtHow to recognise itHai người cùng lấy phần cuối cùng — mất tiền thật thì CP, chỉ sai trên màn hình thì AP.Two users claim the last unit: real money lost means CP, a wrong number on screen means AP.
02
Latency vs Throughput
Luồng & giao tiếpFlow & communication
Trả lời nhanh hay xử lý được nhiều.Fast replies or total volume.
Gom lô chia chi phí cố định cho nhiều đơn vị công việc nên thông lượng tăng, nhưng đơn vị đầu tiên phải nằm chờ những đơn vị sau.Batching spreads a fixed cost across many units so throughput rises, but the first item waits for the rest of the batch.
Dùng khiUse it when
Ưu tiên độ trễ: thanh toán tại quầy, gợi ý khi gõ, đấu giá quảng cáo
Ưu tiên thông lượng: nạp kho dữ liệu, mã hoá video, huấn luyện mô hình
Tách hai loại tải sang hai cụm, mỗi cụm tinh chỉnh một hướng
Latency first: card terminals, search-as-you-type, ad auctions
Throughput first: warehouse loads, video encoding, model training
Split the two workloads onto separate clusters, tuned separately
ĐượcYou get
Gom lô thường cho 5–20 lần thông lượng trên cùng phần cứng
Mỗi 100ms độ trễ cắt được đổi thành phần trăm chuyển đổi
Batching commonly yields 5–20× throughput on the same hardware
Every 100ms of latency removed shows up in conversion
MấtYou pay
Lô lớn làm p99 tệ hơn p50 hàng chục lần
Chạy trên 70% mức sử dụng thì thời gian chờ tăng phi tuyến
Large batches make p99 tens of times worse than p50
Past 70% utilisation, wait time climbs non-linearly
Đánh đổiThe trade-offChọn thông lượng là đổi thời gian chờ của từng request để lấy tổng lượng công việc lớn hơn trên cùng số máy.Choosing throughput trades each request's waiting time for more total work on the same machines.
Dấu hiệu nhận biếtHow to recognise itCó người đang ngồi nhìn màn hình chờ hay không.Is a human staring at a screen, waiting?
03
SQL vs NoSQL
Mô hình lưu trữStorage model
Schema cố định hay linh hoạt.Fixed schema or flexible.
Khác biệt không nằm ở ngôn ngữ truy vấn mà ở chỗ ai chịu trách nhiệm giữ dữ liệu đúng hình dạng: cơ sở dữ liệu hay code của bạn.The difference is not the query language but who keeps data in the right shape: the database, or your code.
Dùng khiUse it when
SQL: kế toán, đơn hàng, mọi miền có báo cáo chưa biết trước
NoSQL: phiên, chuỗi thời gian, feed, dữ liệu thưa và không đồng nhất
Mặc định PostgreSQL — JSONB phủ được phần lớn nhu cầu document
SQL: accounting, orders, any domain with unpredictable reporting
NoSQL: sessions, time series, feeds, sparse heterogeneous data
Default to PostgreSQL — JSONB covers most document needs
ĐượcYou get
SQL chặn lỗi dữ liệu ở tầng lưu trữ, không phải ở code review
NoSQL mở rộng ngang gần tuyến tính với p99 ổn định
SQL blocks data bugs at the storage layer, not at code review
NoSQL scales out near-linearly with stable p99
MấtYou pay
“Schemaless” chỉ nghĩa là schema không được kiểm tra
Chọn sai khoá phân mảnh nghĩa là chép lại toàn bộ dữ liệu
“Schemaless” only means the schema is not checked
A bad shard key means copying the entire dataset
Đánh đổiThe trade-offChọn NoSQL là đổi khả năng đặt câu hỏi mới về dữ liệu để lấy tốc độ ổn định trên đúng những câu hỏi đã biết trước.Choosing NoSQL trades the ability to ask new questions of your data for predictable speed on the questions you already knew.
Dấu hiệu nhận biếtHow to recognise itKhông đoán được sáu tháng nữa người ta hỏi dữ liệu này thế nào thì dùng SQL.If you cannot predict how this data will be queried in six months, use SQL.
04
Vertical vs Horizontal Scaling
Hình dạng hệ thốngSystem shape
Máy to hơn hay nhiều máy hơn.Bigger box or more boxes.
Mở rộng dọc đổi tiền lấy công suất mà không đụng vào code. Mở rộng ngang đổi độ phức tạp lấy trần công suất gần như không giới hạn.Vertical trades money for capacity without touching code. Horizontal trades complexity for a ceiling that is effectively unlimited.
Dùng khiUse it when
Dọc: node ghi của cơ sở dữ liệu, giai đoạn đầu của mọi sản phẩm
Ngang: tầng web không trạng thái, worker hàng đợi, tải lên xuống theo giờ
Nâng cấp máy trước — nó mua cho bạn 6–18 tháng làm việc tử tế
Vertical: database write nodes, the first phase of every product
Horizontal: stateless web tiers, queue workers, load that swings hourly
Resize first — it buys 6–18 months to do the work properly
ĐượcYou get
Nâng cấp máy gần như không tốn giờ kỹ sư
Nhiều node biến cái chết của một máy thành sự kiện bình thường
Resizing costs almost no engineering time
Many nodes turn a machine death into a routine event
MấtYou pay
Giá tăng nhanh hơn công suất ở phân khúc cao, và có trần cứng
Nhiều node kéo theo cân bằng tải, discovery, log, tracing
Price rises faster than capacity at the top, and the ceiling is hard
Many nodes drag in load balancing, discovery, logs, tracing
Đánh đổiThe trade-offChọn mở rộng ngang là đổi sự đơn giản của một tiến trình duy nhất để lấy khả năng vượt trần phần cứng và sống sót khi một máy chết.Choosing horizontal scaling trades the simplicity of a single process for passing hardware ceilings and surviving a machine dying.
Dấu hiệu nhận biếtHow to recognise itMất một máy nghĩa là mất dịch vụ — đó là bài toán sẵn sàng, không phải công suất.If losing one machine means losing the service, that is an availability problem, not a capacity one.
05
Monolith vs Microservices
Hình dạng hệ thốngSystem shape
Một khối triển khai hay nhiều khối.One deployable or many.
Đây trước hết là quyết định về tổ chức con người, sau đó mới là quyết định kỹ thuật: bạn đang mua quyền phát hành độc lập cho từng đội.This is an organisational decision first and a technical one second: you are buying each team the right to release independently.
Dùng khiUse it when
Monolith: gần như mọi sản phẩm dưới 30 kỹ sư
Microservices: nhiều đội có ranh giới sở hữu rõ, tải mở rộng lệch hẳn nhau
Tách theo miền nghiệp vụ, không tách theo tầng kỹ thuật
Monolith: nearly any product under 30 engineers
Microservices: several owning teams, workloads that scale very differently
Split along business domains, never along technical layers
ĐượcYou get
Monolith có giao dịch nguyên tử thật và refactor được compiler kiểm tra
Microservices cắt thời gian các đội chờ nhau khi phát hành
A monolith has real atomic transactions and compiler-checked refactors
Microservices remove the waiting built into a shared release train
MấtYou pay
Mỗi lời gọi mạng thêm timeout, thành công một phần, retry trùng lặp
Nghiệp vụ xuyên service không có rollback, phải tự viết bù trừ
Every network call adds timeouts, partial success, duplicate retries
Cross-service workflows have no rollback, only compensation you write
Đánh đổiThe trade-offChọn microservices là đổi tính nhất quán miễn phí và sự đơn giản khi debug để lấy quyền phát hành độc lập cho từng đội.Choosing microservices trades free consistency and easy debugging for each team's right to release independently.
Dấu hiệu nhận biếtHow to recognise itKhông kể được tên đội trực đêm cho từng service thì đó chưa phải microservices.If you cannot name the team on call for each service, these are not microservices.
06
Strong vs Eventual Consistency
Nhất quán dữ liệuData consistency
Dữ liệu mới nhất hay đọc nhanh hơn.Latest data or faster reads.
Giữa hai cực có các mức trung gian rất hữu dụng và ít được dùng: đọc-thấy-ghi-của-chính-mình, đọc đơn điệu, nhất quán theo phiên.Between the extremes sit useful, underused middle levels: read-your-writes, monotonic reads, session consistency.
Dùng khiUse it when
Mạnh: số dư, tồn kho lúc bán, đặt chỗ, thay đổi quyền
Cuối cùng: lượt thích, người theo dõi, kết quả tìm kiếm, bảng xếp hạng
Ghim đọc vào leader một khoảng ngắn sau mỗi lần ghi của cùng người dùng
Strong: balances, inventory during a sale, reservations, permissions
Pin reads to the leader briefly after each of that user's writes
ĐượcYou get
Nhất quán mạnh xoá lớp bug chỉ xuất hiện dưới tải cao
Nhất quán cuối cùng cho đọc từ replica đặt gần người dùng
Strong removes the bug class that only appears under load
Eventual lets you read from replicas placed near users
MấtYou pay
Nhất quán mạnh đưa độ trễ mạng vào mỗi lần ghi
Độ trễ đồng bộ giãn ra đúng lúc hệ thống đang tải nặng
Strong puts network latency on every write path
Replication lag stretches exactly when the system is loaded
Đánh đổiThe trade-offChọn nhất quán cuối cùng là đổi lời hứa “lần đọc kế tiếp luôn đúng” để lấy độ trễ thấp và khả năng đọc được khi node ghi đang chết.Choosing eventual consistency trades the promise that the next read is correct for low latency and readable data while the write node is down.
Dấu hiệu nhận biếtHow to recognise itHỏi “nếu người dùng thấy dữ liệu của 3 giây trước thì sao”. Không sao thì đừng trả tiền cho nhất quán mạnh.Ask what happens if a user sees data from three seconds ago. If nothing, don't pay for strong consistency.
07
Normalization vs Denormalization
Mô hình lưu trữStorage model
Ít bản sao hay đọc dễ.Fewer copies or easy reads.
Phi chuẩn hoá là ráp sẵn dữ liệu lúc ghi thay vì lúc đọc. Cái giá luôn giống nhau: từ lúc đó, mọi đường ghi phải cập nhật bản sao.Denormalisation assembles data at write time instead of read time. The price is constant: from then on, every write path must update the copy.
Dùng khiUse it when
Chuẩn hoá: dữ liệu giao dịch, sổ cái, mọi thứ ghi nhiều so với đọc
Phi chuẩn hoá: trang sản phẩm, feed, màn hình đọc hàng nghìn lần mỗi lần ghi
Từ tỷ lệ đọc/ghi khoảng 100:1 trở lên mới bắt đầu có lãi
Denormalised: product pages, feeds, screens read thousands of times per write
It only starts paying from a read/write ratio around 100:1
ĐượcYou get
Chuẩn hoá làm dữ liệu sai trở nên bất khả thi ở tầng lưu trữ
Phi chuẩn hoá cắt độ trễ đọc từ hàng chục mili giây xuống dưới 5
Normalisation makes wrong data impossible at the storage layer
Denormalisation cuts read latency from tens of milliseconds to under five
MấtYou pay
JOIN nhiều bảng lớn là nơi bộ tối ưu hay chọn sai kế hoạch
Dữ liệu phi chuẩn hoá sẽ trôi lệch — không phải nếu, mà là khi nào
Multi-table JOINs are where planners pick bad plans
Denormalised data drifts — not if, but when
Đánh đổiThe trade-offChọn phi chuẩn hoá là đổi việc có một nguồn sự thật duy nhất để lấy lượt đọc nhanh và dự đoán được.Choosing denormalisation trades having a single source of truth for reads that are fast and predictable.
Dấu hiệu nhận biếtHow to recognise itĐếm tỷ lệ đọc trên ghi của đúng màn hình đó, không đếm của cả hệ thống.Count the read-to-write ratio of that one screen, not of the whole system.
08
Read vs Write Optimization
Mô hình lưu trữStorage model
Chỉnh cho đọc hay chỉnh cho ghi.Tune for reads or writes.
Index, bản sao tính sẵn và bộ đệm làm đọc nhanh lên bằng cách trả trước công sức lúc ghi. Bỏ chúng đi thì ngược lại.Indexes, precomputed copies and caches make reads fast by paying up front at write time. Remove them and the bet inverts.
Dùng khiUse it when
Nghiêng đọc: danh mục, hồ sơ, báo cáo, bảng điều khiển nội bộ
B-trees read well; LSM-trees write well but compaction eats I/O unpredictably
ĐượcYou get
Index đúng thường biến truy vấn từ vài giây xuống vài mili giây
Ghi tuần tự cho thông lượng nạp dữ liệu cao hơn nhiều lần
The right index takes a query from seconds to milliseconds
Sequential writes give many times the ingest throughput
MấtYou pay
Index thừa tốn dung lượng, làm chậm mọi lần ghi, làm bộ tối ưu bối rối
Compaction chạy đúng lúc tải cao thì p99 tăng đột biến
A surplus index costs storage, slows every write, confuses the planner
Compaction landing at peak load spikes p99
Đánh đổiThe trade-offChọn tối ưu đọc là đổi thông lượng ghi và dung lượng đĩa để lấy truy vấn nhanh và ổn định.Choosing read optimisation trades write throughput and disk space for fast, stable queries.
Dấu hiệu nhận biếtHow to recognise itNhìn tỷ lệ ghi/đọc trong một giờ cao điểm thật, đừng nhìn ước lượng.Look at the write/read ratio during a real peak hour, not at an estimate.
09
Caching vs Freshness
Mô hình lưu trữStorage model
Cũ và nhanh hay mới và chậm.Stale and fast or fresh.
Mọi cache đều trả lời bằng dữ liệu của quá khứ. TTL chỉ là cách bạn tuyên bố mình chấp nhận quá khứ bao xa.Every cache answers with data from the past. TTL is just how you declare how far into the past you will accept.
Dùng khiUse it when
Nên cache: tính toán nặng, dữ liệu tham chiếu, API tính tiền theo lượt gọi
Không nên: số dư, tồn kho lúc thanh toán, quyền truy cập
Ưu tiên khoá có phiên bản thay vì xoá chủ động
Do cache: heavy computations, reference data, per-call billed APIs
Don't: balances, inventory at checkout, access permissions
Prefer versioned keys over explicit invalidation
ĐượcYou get
Thường giảm tải nguồn 80–95% với dữ liệu đọc nhiều
Là quyết định dễ hoàn tác nhất trong cả danh sách này
Typically removes 80–95% of source load for read-heavy data
The most reversible decision on this entire list
MấtYou pay
Xoá cache đúng lúc là bài toán khó kinh điển
Khoá nóng hết hạn có thể kéo hàng nghìn request cùng lao vào nguồn
Invalidating at the right moment is the classic hard problem
An expiring hot key can send thousands of requests at the source at once
Đánh đổiThe trade-offChọn cache là đổi độ tươi của dữ liệu để lấy độ trễ thấp và giảm tải cho nguồn.Choosing to cache trades data freshness for low latency and reduced load on the source.
Dấu hiệu nhận biếtHow to recognise itNếu dữ liệu cũ khiến người dùng ra một quyết định sai không hoàn tác được thì đừng cache.If stale data leads a user to an irreversible wrong decision, don't cache it.
10
Push vs Pull
Luồng & giao tiếpFlow & communication
Server gửi hay client hỏi.Server sends or client asks.
Trục đánh đổi là ai chịu chi phí biết được “có gì mới”, và độ trễ thông báo là bao nhiêu.The axis is who pays the cost of discovering that something is new, and how long the notification takes.
Dùng khiUse it when
Pull: đồng bộ nền, cấu hình, thu thập số liệu, tích hợp nội bộ
Push: tin nhắn, thông báo, bảng giá trực tiếp, cộng tác tài liệu
Kiểu lai thường đúng: push tín hiệu ngắn, client pull lấy chi tiết
Push: chat, notifications, live prices, document collaboration
The hybrid usually wins: push a small signal, let the client pull detail
ĐượcYou get
Pull chỉ là HTTP: không giữ kết nối, dễ thử lại, chạy sau mọi load balancer
Push cho độ trễ dưới một giây và bỏ hẳn lưu lượng hỏi vô ích
Pull is plain HTTP: no held connections, trivially retryable, works anywhere
Push gives sub-second latency and removes all wasted polling
MấtYou pay
100 nghìn client hỏi mỗi 10 giây là 10 nghìn request mỗi giây gần như vô ích
Push cần heartbeat, kết nối lại, và vẫn có thể mất sự kiện
100k clients polling every 10s is 10k near-useless requests per second
Push needs heartbeats, reconnects, and can still drop events
Đánh đổiThe trade-offChọn push là đổi sự đơn giản không trạng thái của HTTP để lấy độ trễ thông báo dưới một giây.Choosing push trades the stateless simplicity of HTTP for sub-second notification latency.
Dấu hiệu nhận biếtHow to recognise itHơn 90% lượt hỏi trả về “không có gì” thì chi phí đó đã đủ để chuyển sang push.If over 90% of polls return “nothing,” that waste already justifies push.
11
Sync vs Async Communication
Luồng & giao tiếpFlow & communication
Chờ phản hồi hay gửi rồi đi tiếp.Wait for the reply or hand it off.
Trong thực tế bạn hầu như luôn ở mức giao hàng “ít nhất một lần”, nghĩa là consumer bắt buộc phải xử lý được tin nhắn trùng.In practice you almost always land on at-least-once delivery, which means consumers must tolerate duplicates.
Dùng khiUse it when
Đồng bộ: đăng nhập, kiểm tra quyền, tính giá, xác thực thẻ
Bất đồng bộ: gửi email, tạo ảnh thu nhỏ, xuất báo cáo, đồng bộ bên thứ ba
Cảnh báo theo tuổi tin nhắn cũ nhất, không theo số lượng trong hàng đợi
Alert on the age of the oldest message, not on queue depth
ĐượcYou get
Đồng bộ cho luồng code thẳng và stack trace chỉ đúng chỗ hỏng
Hàng đợi hấp thụ đỉnh tải gấp mười thay vì trả về lỗi 503
Sync gives straight-line code and a stack trace that points at the fault
Queues absorb a 10× spike instead of returning 503s
MấtYou pay
Năm dịch vụ nối tiếp, mỗi cái 99,9%, cho tổng khoảng 99,5%
Hàng đợi tồn đọng là chế độ lỗi im lặng, mọi thứ vẫn xanh
Five chained services at 99.9% each give roughly 99.5% together
A growing backlog is a silent failure — the dashboard stays green
Đánh đổiThe trade-offChọn bất đồng bộ là đổi việc biết ngay kết quả và sự dễ dàng khi debug để lấy khả năng chịu đỉnh tải và cô lập lỗi.Choosing async trades immediate results and easy debugging for spike tolerance and isolated failures.
Dấu hiệu nhận biếtHow to recognise itNgười dùng không cần thấy kết quả trên màn hình tiếp theo thì việc đó thuộc về hàng đợi.If the user doesn't need the result on the next screen, that work belongs in a queue.
12
Replication vs Partitioning
Nhất quán dữ liệuData consistency
Sao chép dữ liệu hay chia nhỏ dữ liệu.Copy data or split data.
Sao chép giải bài toán chịu lỗi và mở rộng đọc. Phân mảnh giải bài toán dung lượng và mở rộng ghi. Hệ thống lớn dùng cả hai.Replication solves fault tolerance and read scale. Partitioning solves capacity and write scale. Large systems use both.
Dùng khiUse it when
Sao chép: gần như mọi hệ thống production, ngay từ đầu
Phân mảnh: vượt đĩa một node, vượt khả năng ghi một leader, yêu cầu pháp lý
Dùng nhiều mảnh logic hơn số node vật lý, ví dụ 1024 mảnh trên 8 node
Replicate: nearly every production system, from day one
Partition: past one node's disk, past one leader's writes, legal residency
Use more logical partitions than physical nodes — say 1024 across 8
ĐượcYou get
Sao chép là cách rẻ nhất để chịu được cái chết của một máy
Phân mảnh gỡ bỏ trần dung lượng và trần ghi
Replication is the cheapest way to survive one machine dying
Partitioning lifts both the capacity and the write ceiling
MấtYou pay
Chuyển leader tự động dễ gây split-brain nếu quorum cấu hình sai
Chọn sai khoá phân mảnh nghĩa là chép lại toàn bộ dữ liệu khi hệ thống vẫn chạy
Automatic failover invites split-brain when quorum settings are wrong
A bad partition key means copying everything while the system stays up
Đánh đổiThe trade-offChọn phân mảnh là đổi giao dịch, JOIN và sự đơn giản khi vận hành để lấy khả năng ghi và lưu trữ vượt giới hạn một máy.Choosing partitioning trades transactions, JOINs and operational simplicity for write and storage capacity beyond one machine.
Dấu hiệu nhận biếtHow to recognise itVấn đề là đọc hoặc chịu lỗi thì cần sao chép; chỉ khi là ghi hoặc dung lượng mới cần phân mảnh.Reads or fault tolerance need replication; only writes or capacity need partitioning.
13
Batch vs Stream Processing
Luồng & giao tiếpFlow & communication
Xử lý theo lô hay xử lý liên tục.In chunks or continuously.
Khác biệt cốt lõi không phải tốc độ mà là ranh giới: lô có điểm bắt đầu và kết thúc rõ ràng, luồng thì không bao giờ kết thúc.The core difference isn't speed, it's boundedness: a batch has a start and an end, a stream never ends.
Dùng khiUse it when
Lô: báo cáo cuối ngày, tính lương, huấn luyện mô hình, đối soát
Luồng: phát hiện gian lận, cảnh báo vận hành, bảng điều khiển trực tiếp
Dùng thời gian sự kiện, và quyết định rõ cách xử lý dữ liệu tới trễ
Batch: end-of-day reports, payroll, model training, reconciliation
Stream: fraud detection, operational alerting, live dashboards
Use event time, and decide the late-data policy explicitly
ĐượcYou get
Job lô chạy lại được, và khả năng chạy lại là thứ cứu bạn mỗi lần có bug logic
Luồng cho kết quả trong vài giây và làm phẳng tải cả ngày
Batch jobs rerun, and rerunnability saves you every time a logic bug appears
Streams give results in seconds and flatten load across the day
MấtYou pay
Cửa sổ chạy lô co lại theo dữ liệu: job hai giờ hôm nay là job chín giờ năm sau
Sự kiện tới trễ là nguồn bug tinh vi nhất trong hệ luồng
The batch window shrinks as data grows: today's 2h job is next year's 9h job
Late events are the subtlest bug source in streaming systems
Đánh đổiThe trade-offChọn xử lý luồng là đổi khả năng chạy lại dễ dàng và chi phí thấp để lấy kết quả tính bằng giây thay vì bằng giờ.Choosing streaming trades easy reruns and low cost for results in seconds instead of hours.
Dấu hiệu nhận biếtHow to recognise itKết quả chậm một giờ vẫn còn giá trị hành động thì dùng lô.If a result an hour later is still actionable, use batch.
14
Stateful vs Stateless
Hình dạng hệ thốngSystem shape
Server giữ trạng thái hay một kho bên ngoài giữ.The server holds it or a store does.
Không trạng thái không có nghĩa hệ thống không có trạng thái — nó chỉ có nghĩa trạng thái đã dời sang thành phần được thiết kế để giữ nó.Stateless doesn't mean the system has no state — it means the state moved to a component designed to hold it.
Dùng khiUse it when
Không trạng thái: API web, worker hàng đợi, mọi thứ cần co giãn tự động
Có trạng thái: máy chủ game, phiên WebSocket, node giữ cửa sổ xử lý luồng
Token ngắn hạn dưới 15 phút kèm refresh token để thu hồi có ý nghĩa
Stateless: web APIs, queue workers, anything that autoscales
Stateful: game servers, WebSocket sessions, stream nodes holding windows
Short-lived tokens under 15 minutes plus refresh, so revocation means something
ĐượcYou get
Thêm node, bớt node, thay node — không ai nhận ra
Có trạng thái cho độ trễ thấp nhất vì dữ liệu nóng nằm ngay trong bộ nhớ
Add a node, drop a node, replace a node — nobody notices
Stateful gives the lowest latency because hot data sits in memory
MấtYou pay
Không trạng thái thêm 1–5ms vào mỗi request và một phụ thuộc phải luôn sống
Sticky session làm tải lệch và mất trạng thái khi node được thay
Stateless adds 1–5ms per request and a dependency that must stay alive
Sticky sessions skew load and lose state when a node is replaced
Đánh đổiThe trade-offChọn không trạng thái là đổi độ trễ truy cập trạng thái trong bộ nhớ để lấy quyền thay thế bất kỳ node nào vào bất kỳ lúc nào.Choosing statelessness trades in-memory access latency for the right to replace any node at any moment.
Dấu hiệu nhận biếtHow to recognise itKhông tắt được một node ngẫu nhiên ngay bây giờ mà không ai để ý thì service của bạn đang có trạng thái.If you can't kill a random node right now unnoticed, your service is stateful.
15
Redundancy vs Cost
Hình dạng hệ thốngSystem shape
Càng nhiều bản dự phòng, càng nhiều tiền.More spare copies, more cost.
Dự phòng chỉ có tác dụng khi các bản sao nằm ở miền lỗi khác nhau và khi cơ chế chuyển đổi thực sự đã từng chạy.Redundancy only works when copies sit in different failure domains and the failover mechanism has actually run.
Dùng khiUse it when
Cao: thanh toán, xác thực, dữ liệu không tạo lại được, SLA có tiền
Thấp: môi trường thử nghiệm, công cụ nội bộ, job phân tích chạy lại được
Phân tầng theo mức quan trọng, đừng trả giá đồng hạng cho mọi thứ
Low: test environments, internal tools, rerunnable analytics jobs
Tier by criticality; don't pay the same price for everything
ĐượcYou get
Biến sự cố phần cứng từ khủng hoảng thành một dòng log
Bản sao nhiều vùng cho phép bảo trì mà không cần cửa sổ ngừng dịch vụ
Turns hardware failure from a crisis into a log line
Copies across zones allow maintenance with no downtime window
MấtYou pay
Chi phí tuyến tính hằng tháng, lợi ích chỉ là xác suất
Không chặn được lỗi tương quan: bug, cấu hình sai, chứng chỉ hết hạn
Cost is linear and monthly while the benefit is probabilistic
It doesn't stop correlated failures: bugs, bad config, expired certificates
Đánh đổiThe trade-offChọn dự phòng cao là đổi một khoản chi cố định hằng tháng để lấy việc loại bỏ một lớp sự cố khỏi danh sách những thứ có thể làm sập bạn.Choosing high redundancy trades a fixed monthly bill for removing an entire failure class from the list of things that can take you down.
Dấu hiệu nhận biếtHow to recognise itNhân chi phí một giờ gián đoạn với số giờ dự kiến mỗi năm, rồi so với hoá đơn dự phòng.Multiply the cost of an hour of downtime by expected annual downtime, then compare with the redundancy bill.
Bảng đánh đổiThe trade-off table
Cột cuối là mức khó đảo ngược, từ 1 (tháo ra trong một giờ) tới 5 (dự án nhiều tháng). Đọc cột đó trước: những dòng 5 điểm là những quyết định nên trì hoãn tới lúc cuối cùng có thể.The last column scores reversibility from 1 (rip it out in an hour) to 5 (a multi-month project). Read it first: the fives are the decisions to defer as long as you can.
Không trần, chịu lỗi nodeNo ceiling, survives node loss
05
Monolith
Giao dịch thật, refactor dễReal transactions, easy refactors
Microservices
Đội phát hành độc lậpIndependent team releases
06
Strong
Đọc luôn thấy dữ liệu mớiReads always current
Eventual
Đọc nhanh, đọc gần người dùngFast reads, reads near users
07
Normalized
Một nguồn sự thậtOne source of truth
Denormalized
Đọc nhanh, đoán trước đượcFast, predictable reads
08
Reads
Truy vấn nhanhFast queries
Writes
Nạp dữ liệu nhanhFast ingest
09
Cached
Trễ thấp, giảm tải nguồnLow latency, less source load
Fresh
Luôn đúng thời điểmAlways current
10
Push
Thông báo dưới một giâySub-second notification
Pull
Đơn giản, không trạng tháiSimple and stateless
11
Sync
Biết ngay, dễ debugImmediate, easy to debug
Async
Chịu đỉnh tải, cô lập lỗiSpike tolerance, isolation
12
Replicate
Chịu lỗi, mở rộng đọcFault tolerance, read scale
Partition
Vượt trần ghi và dung lượngPast write and storage ceilings
13
Batch
Rẻ, chạy lại dễCheap, easy reruns
Stream
Kết quả trong vài giâyResults in seconds
14
Stateful
Trễ thấp nhấtLowest latency
Stateless
Node thay được tự doAny node is replaceable
15
Redundant
Loại bỏ một lớp sự cốOne failure class removed
Cheap
Chi ít, đi nhanhSpend less, move faster
Sai lầm thường gặpAnti-patterns
Tám cách phổ biến nhất để trả giá của một đánh đổi mà không nhận được thứ mình mua.The eight most common ways to pay a trade-off's price without receiving what you bought.
Sai lầmMistake
Vì sao saiWhy it's wrong
Sửa thế nàoThe fix
Microservices cho đội 5 ngườiMicroservices for a team of five
Nhận toàn bộ chi phí phân tán mà không có lợi ích tổ chức nào.You take the full distributed cost with none of the organisational benefit.
Monolith có module rõ ràng; đặt ranh giới trong code trước, trong mạng sau.A modular monolith; draw boundaries in code first, in the network later.
“Cần realtime” mà không ai nêu ngưỡng“We need realtime” with no threshold
Realtime là một dải, không phải một trạng thái. Không ngưỡng thì không kiểm chứng được.Realtime is a range, not a state. Without a number nothing is verifiable.
Hỏi “chậm bao nhiêu thì mất giá trị”. Đa số câu trả lời là vài phút.Ask how late before it loses value. Most answers are minutes.
Phân mảnh khi chưa dùng hết cache và replicaPartitioning before caches and replicas
Phân mảnh đắt gấp nhiều bậc và gần như không thể hoàn tác.Partitioning is orders of magnitude costlier and near-impossible to undo.
Thứ tự: index → cache → replica đọc → máy lớn hơn → rồi mới phân mảnh.The order is: indexes → cache → read replicas → bigger machine → then partition.
Retry không backoff, không idempotentRetries without backoff or idempotency
Retry đồng loạt biến sự cố nhỏ thành bão request và tạo dữ liệu trùng.Synchronised retries turn a small incident into a storm and duplicate data.
Backoff mũ có jitter, giới hạn số lần, khoá idempotency cho mọi thao tác ghi.Exponential backoff with jitter, a cap, and an idempotency key on every write.
Đo hiệu năng bằng giá trị trung bìnhMeasuring performance by the average
Trung bình che đúng nhóm p99 đang bỏ đi.The average hides the p99 users who are leaving.
Đặt SLO theo p95 và p99, hiển thị histogram thay vì một con số.Set SLOs at p95 and p99 and show a histogram, not one number.
Denormalize mà không có job đối chiếuDenormalising with no reconciliation job
Bản sao chắc chắn sẽ lệch, và không ai phát hiện cho tới khi khách hàng phàn nàn.The copy will drift, and nobody notices until a customer complains.
Viết job đối chiếu ngay trong cùng PR với việc phi chuẩn hoá.Write the reconciliation job in the same PR as the denormalisation.
Ba bản sao trên cùng một máy chủ vật lýThree replicas on one physical host
Ba bản sao chung một miền lỗi là một lần bảo vệ, trả tiền ba lần.Three copies in one failure domain is one unit of protection billed three times.
Trải bản sao qua các AZ khác nhau, kiểm tra bằng cấu hình chứ không bằng niềm tin.Spread copies across zones and verify it in configuration, not by belief.
Multi-region mà chưa từng thử failoverMulti-region without testing failover
Bạn mua hoá đơn chứ không mua khả năng chịu lỗi.You bought a bill, not fault tolerance.
Diễn tập failover theo lịch, trên production, trước khi mở rộng thêm vùng.Rehearse failover on a schedule, on production, before adding regions.
Ba câu cần nhớThree things to remember
Không có kiến trúc đúng, chỉ có kiến trúc đúng với con số tải, ngân sách và đội ngũ hiện tại của bạn — và cả ba đều đổi theo thời gian.There is no correct architecture, only one correct for your current load numbers, budget and team — and all three change over time.
Hạn chế là thứ bạn chịu đựng, đánh đổi là thứ bạn chọn; nếu không nói được mình đang trả cái gì thì bạn chưa quyết định, bạn chỉ đang làm theo mặc định.A limitation is something you endure; a trade-off is something you choose. If you can’t say what you’re paying, you haven’t decided, you’ve defaulted.
Ưu tiên quyết định rẻ khi sai — cache, replica đọc và hàng đợi tháo ra trong một ngày, còn khoá phân mảnh, ranh giới service và mô hình nhất quán đi cùng bạn nhiều năm.Prefer decisions that are cheap to be wrong about — caches, read replicas and queues come out in a day, while partition keys, service boundaries and consistency models stay with you for years.