AllianceProject Handbook
← Knowledge

Quy mô và hiệu năng

Chất lượng ở quy mô 500.000 người dùng

Alliance App hướng tới 500.000 người dùng. Ở quy mô đó, một lỗi hiếm vẫn là hàng trăm người, và một bản release xấu lan nhanh hơn khả năng phản ứng thủ công. Bài này nói cách QC phải đổi theo.

Cập nhật 12/09/2026quy môchất lượngshift left

Con số phải nhớ

Mục tiêu quy mô của Alliance App là 500.000 người dùng. Hãy đổi mọi tỷ lệ phần trăm ra số người thật trước khi nói "chấp nhận được":

Tỷ lệ nghe có vẻ nhỏSố người dùng bị ảnh hưởng
5%25.000
1%5.000
0,5%2.500
0,1%500
0,01%50

Luật viết báo cáo: mọi lỗi đều báo kèm số người, không chỉ báo tỷ lệ. "Tỷ lệ lỗi 0,3%" nghe như chuyện nhỏ. "1.500 người không gửi được tin nhắn" thì không ai nhầm lẫn về mức độ.

Hệ quả trực tiếp với module Bán hàng: 0,1% đơn bị trùng, với 20.000 đơn một ngày, là 20 đơn sai mỗi ngày — mỗi đơn là một cuộc gọi khiếu nại và một lần hoàn tiền. Đó là lý do chuẩn riêng từng module đặt mức dung sai cho tiền bằng không.

Ba thứ đổi hẳn khi vượt mốc

1. Lỗi hiếm trở thành lỗi thường xuyên

Ở 500 người dùng, một lỗi chỉ xảy ra khi "mất mạng đúng lúc bấm nút" gần như không bao giờ thấy. Ở 500.000 người dùng, nó xảy ra mỗi ngày, nhiều lần.

Nghĩa là mọi trường hợp biên trong bài những điều bắt buộc với dev chuyển từ lý thuyết sang chắc chắn sẽ xảy ra. Race condition, timeout, bấm hai lần, xoay màn hình giữa chừng, app bị hệ điều hành kill khi đang gửi — tất cả đều sẽ được nghiệm thu bởi người dùng thật nếu ta không chặn trước.

2. Phát hiện thủ công không còn kịp

Một bản release xấu bật 100% có thể chạm 500.000 người trong vài giờ. Không có đội hỗ trợ nào phản ứng kịp bằng tay.

Nghĩa là phát hiện phải tự động và rollback phải nhanh hơn tốc độ lan. Toàn bộ cơ chế ở release từng phần và feature flaggiám sát và cảnh báo không phải là thứ "làm cho đẹp" — ở quy mô này chúng là điều kiện sống còn.

3. Tải trở thành một loại lỗi riêng

Code đúng về logic vẫn có thể hỏng vì tải: truy vấn không có chỉ mục, vòng lặp gọi cơ sở dữ liệu, kết nối thời gian thực giữ quá lâu, bộ nhớ rò rỉ chậm. Những lỗi này không xuất hiện ở môi trường test với 10 người dùng.

Nên phải có một loại quality gate riêng cho hiệu năng — xem test tải và hiệu năng.

Ngân sách lỗi

Không có hệ thống nào đạt 100%. Cách quản lý đúng là định trước mức hỏng được phép, rồi dùng nó để quyết định làm tính năng hay làm ổn định.

Mức sẵn sàng mục tiêuThời gian hỏng cho phép mỗi thángVới 500.000 người
99,9%43 phútKhoảng 22.000 người bị ảnh hưởng mỗi lần hỏng 1 giờ
99,5%3 giờ 39 phútQuá lỏng cho module Bán hàng
99,95%21 phútMức nên hướng tới cho Bán hàng

Cách dùng ngân sách lỗi:

  • Còn ngân sách: được phép release nhanh, được phép thử nghiệm.
  • Hết ngân sách trong tháng: dừng phát hành tính năng mới, cả đội chuyển sang làm ổn định cho tới đầu tháng sau.

Luật này quan trọng ở chỗ nó tự động chuyển ưu tiên, không cần ai đi thuyết phục ai. Nó cũng chấm dứt tranh cãi muôn thuở giữa "làm thêm tính năng" và "sửa cho chắc".

Thang release đã tính lại theo quy mô

Các nấc phần trăm nhỏ ở quy mô này vẫn là nhóm người đủ lớn để đọc được số liệu:

NấcTỷ lệSố ngườiChờ tối thiểuVì sao đủ
0Nội bộ~501 ngàyBắt lỗi thô
10,5%2.5001 ngàyĐủ để thấy crash và lỗi API
22%10.0001 ngàyĐủ để thấy chỉ số hành vi
310%50.0002 ngàyĐủ để thấy tác động nghiệp vụ
450%250.0002 ngàyKiểm tra tải một nửa
5100%500.000Xoá cờ trong 2 sprint

Tính năng chạm tới tiền, quyền hoặc dữ liệu cá nhân thì bắt đầu từ nấc 1 ở mức 0,1% và gấp đôi thời gian chờ ở mỗi nấc.

Điểm mấu chốt: nấc 1 và 2 tồn tại vì ở đó thiệt hại còn sửa được. Nhảy thẳng lên 100% là đánh cược toàn bộ tập người dùng vào chất lượng của một lần review.

Dữ liệu lớn lên cũng gây lỗi

Phần lớn lỗi quy mô không nằm ở số người đồng thời, mà ở lượng dữ liệu tích lại:

Chỗ hay vỡBiểu hiệnChặn bằng cách nào
Danh sách không phân trangApp chậm dần rồi treo với người dùng cũBắt buộc phân trang bằng con trỏ, không dùng offset
Truy vấn thiếu chỉ mụcNhanh ở test, chậm chết ở productionReview kế hoạch truy vấn cho mọi truy vấn mới
Tải hết lịch sử chatTốn bộ nhớ, crash máy yếuChỉ tải cửa sổ gần nhất
Báo cáo doanh số quét toàn bảngTimeout khi dữ liệu lớnBảng tổng hợp sẵn, tính theo lô
Migration khoá bảngNgừng dịch vụ khi triển khaiMigration phải chạy được trên bảng lớn, có bước quay lui

Quy tắc bắt buộc: mọi truy vấn mới phải được thử trên tập dữ liệu cỡ production, không phải trên vài chục dòng dữ liệu mẫu. Có một bộ dữ liệu giả cỡ lớn là hạ tầng test bắt buộc, không phải thứ tuỳ chọn.

Đây đúng là shift left: tìm ra truy vấn chậm lúc viết code tốn 10 phút, tìm ra lúc người dùng thứ 300.000 đăng ký tốn một đêm mất ngủ.

Ba lớp bảo vệ, xếp theo thứ tự

LớpChặn cái gìỞ đâu
Ngăn lỗi sinh raLỗi logic, lỗi biên, truy vấn chậmYêu cầu rõ, review, test, quality gate
Giới hạn thiệt hạiLỗi đã lọt raFeature flag, release từng phần, giới hạn tần suất
Phục hồi nhanhLỗi đã ảnh hưởng người dùngCảnh báo tự động, rollback, quy trình sự cố

Ở quy mô nhỏ, chỉ lớp một là đủ sống. Ở 500.000 người dùng, thiếu lớp hai là cá cược, và thiếu lớp ba là tự sát. Một đội tốt đầu tư đều cả ba, và biết rằng lớp một không bao giờ đạt 100%.

Những gì phải có trước khi mở rộng

Danh sách này là điều kiện để đi từ quy mô hiện tại lên mục tiêu. Thiếu mục nào thì chưa mở rộng người dùng.

  • Feature flag chạy được và tắt được trong 30 giây, có người trực biết cách tắt.
  • Cảnh báo tự động cho mọi chỉ số trong giám sát và cảnh báo.
  • Test tải đạt mục tiêu ở mức gấp đôi tải dự kiến.
  • Bộ dữ liệu thử cỡ lớn, dùng trong pipeline.
  • Quy trình sự cố có người trực và đã diễn tập ít nhất một lần.
  • Đối soát tự động cho module Bán hàng, chạy hằng ngày.
  • Migration đã thử trên bản sao dữ liệu cỡ production.
  • Ngân sách lỗi được đặt và được theo dõi hằng tháng.

Diễn tập ở mục 5 hay bị bỏ nhất. Quy trình sự cố chưa từng chạy thử thì lúc cần sẽ không chạy được — người ta sẽ không nhớ ai gọi ai, tắt cờ ở đâu, rollback bằng lệnh gì.