Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Performance budget & SLO

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn được giao nhiệm vụ test hiệu năng cho một ứng dụng. Bạn viết script k6 thật đẹp, chạy load test, và nhận về một bảng số liệu: p95 latency là 820ms, throughput 340 request/giây, error rate 0.4%. Câu hỏi đầu tiên mà bất kỳ ai — cả bạn lẫn sếp — cũng sẽ hỏi là: "Vậy con số đó là tốt hay xấu?"

Nếu bạn không trả lời được câu hỏi này ngay lập tức, thì bạn đã bỏ qua bước quan trọng nhất của cả quy trình performance testing: đặt mục tiêu trước khi test. Test mà không có tiêu chuẩn để so sánh thì chỉ là thu thập số liệu, không phải kiểm thử. Nó giống như cân một người rồi hỏi "60 kg là nặng hay nhẹ?" — vô nghĩa nếu không biết chiều cao, độ tuổi và mục tiêu sức khỏe.

Bài này nói về hai công cụ giúp bạn định nghĩa "thế nào là đạt" một cách rõ ràng, có thể đo lường và có thể bảo vệ trước cả kỹ sư lẫn cấp quản lý: Performance Budget (ngân sách hiệu năng) và SLO (Service Level Objective — mục tiêu mức dịch vụ). Đây là phần "chiến lược" của nghề performance engineer — thứ phân biệt một người chỉ biết chạy tool với một người biết định hình chất lượng sản phẩm. Khi bạn thành thạo hai khái niệm này, mọi bài test bạn viết sau đó (dùng JMeter, k6, hay gì đi nữa) đều có một cái đích rõ ràng để bám vào.

Khái niệm cốt lõi

Performance Budget — giới hạn đặt ra từ giai đoạn thiết kế

Performance Budget là một tập hợp các giới hạn định lượng mà sản phẩm cam kết không được vượt qua. Điểm mấu chốt: budget được đặt ra ngay từ giai đoạn design/development, chứ không phải sau khi sản phẩm đã chạy và bị người dùng phàn nàn chậm.

Khái niệm này vay mượn từ tài chính. Bạn có một "ngân sách" hiệu năng cố định, và mỗi thành phần bạn thêm vào (một thư viện JavaScript, một ảnh banner, một API call mới) đều "tiêu" một phần ngân sách đó. Khi tổng chi vượt quá ngân sách, bạn buộc phải cắt bớt hoặc tối ưu — giống như khi tiêu quá tiền lương thì phải thắt lưng buộc bụng.

Các loại budget thường gặp:

  • Quantity-based budget (dựa trên số lượng): Page weight < 1 MB, số HTTP request < 50, số lượng font < 3, kích thước JavaScript bundle < 250 KB (nén gzip). Đây là loại dễ đo nhất vì bạn chỉ cần đếm.
  • Timing-based budget (dựa trên thời gian): Time to First Byte (TTFB) < 200ms, Largest Contentful Paint (LCP) < 2.5s, Time to Interactive < 3.8s. Loại này gắn liền với trải nghiệm người dùng thực tế.
  • Rule-based budget (dựa trên quy tắc/điểm số): Ví dụ điểm Lighthouse Performance ≥ 90. Loại này gộp nhiều yếu tố thành một con số tổng hợp.
Với performance testing phía server (đúng trọng tâm khóa học này), budget của bạn sẽ nghiêng về phía: latency tối đa cho mỗi endpoint, throughput tối thiểu phải chịu được, dung lượng payload API tối đa, số lượng database query cho mỗi request. Ví dụ: "Endpoint /api/checkout phải trả về trong 500ms ở p95 khi có 500 người dùng đồng thời, và mỗi lần gọi không được thực hiện quá 8 câu query xuống database."

SLI, SLO, SLA — bộ ba dễ nhầm lẫn

Đây là ba thuật ngữ luôn đi cùng nhau và học viên hay nhầm. Hãy phân biệt thật rõ:

  • SLI (Service Level Indicator)chỉ số. Đây là con số bạn thực sự đo được từ hệ thống. Ví dụ: "tỷ lệ request có latency dưới 300ms trong 5 phút vừa qua là 99.2%". SLI là dữ liệu thô, là sự thật khách quan.
  • SLO (Service Level Objective)mục tiêu. Đây là ngưỡng bạn muốn SLI đạt được. Ví dụ: "99% request phải có latency dưới 300ms trong mỗi khoảng 30 ngày". SLO là mục tiêu nội bộ do đội kỹ thuật đặt ra để tự quản lý chất lượng. Nếu SLI = 99.2% và SLO = 99%, bạn đang đạt mục tiêu.
  • SLA (Service Level Agreement)cam kết hợp đồng. Đây là lời hứa mang tính pháp lý với khách hàng, thường kèm hình phạt (hoàn tiền, phạt hợp đồng) nếu vi phạm. SLA thường được đặt lỏng hơn SLO một chút để có vùng đệm an toàn. Ví dụ SLA cam kết uptime 99.5% nhưng nội bộ đội đặt SLO 99.9% — để khi SLO bị vi phạm, đội có thời gian sửa trước khi chạm ngưỡng vi phạm SLA thật sự.
Một cách nhớ ngắn gọn: SLI là điều bạn đo, SLO là điều bạn nhắm tới, SLA là điều bạn hứa (và bị phạt nếu sai).

Error Budget — vùng đệm cho phép sai

Từ SLO sinh ra một khái niệm cực kỳ hữu dụng: Error Budget (ngân sách lỗi). Nếu SLO của bạn là 99.9% request thành công trong 30 ngày, thì 0.1% còn lại chính là error budget — lượng lỗi bạn được phép "tiêu" mà không vi phạm cam kết.

0.1% của 30 ngày là khoảng 43 phút downtime mỗi tháng. Con số này biến một mục tiêu trừu tượng thành thứ có thể quản lý như tiền bạc. Khi đội phát triển đã "tiêu" hết error budget trong tháng, chính sách thường là: đóng băng tính năng mới, dồn toàn lực vào ổn định hệ thống. Đây là cầu nối tuyệt vời giữa performance engineering và quyết định kinh doanh — nó cho phép đội cân bằng giữa "chạy nhanh, ra tính năng mới" và "giữ hệ thống ổn định".

Trong performance testing, error budget giúp bạn quyết định pass/fail của một bài test một cách công bằng. Thay vì đòi hỏi 0% lỗi (điều gần như không thể ở tải cao), bạn cho phép một tỷ lệ lỗi nằm trong error budget.

Vì sao budget và SLO là bước ĐẦU TIÊN

Điều quan trọng nhất cần khắc cốt ghi tâm: bạn phải xác định budget và SLO trước khi viết bất kỳ dòng script test nào. Lý do rất thực tế — Threshold trong k6 và Assertion trong JMeter (các bài trước và sau đã dạy chi tiết cách viết) chính là hiện thân bằng code của SLO. Nếu bạn chưa biết SLO, bạn không biết đặt threshold ở mức nào, và bài test của bạn sẽ luôn "pass" một cách vô nghĩa vì chẳng có ngưỡng nào để fail.

Tình huống thực tế

Ví dụ 1 — Tiki và ngân sách hiệu năng cho trang sản phẩm

Giả sử đội kỹ thuật của Tiki chuẩn bị phát hành lại (redesign) trang chi tiết sản phẩm. Trước khi thiết kế, họ họp và chốt một performance budget cứng: page weight tối đa 1.2 MB, LCP dưới 2.5 giây trên mạng 4G, và API /product/detail phải phản hồi trong 400ms ở p95 dưới tải 1.000 người dùng đồng thời.

Ba tuần sau, đội frontend hoàn thành bản mới rất đẹp — nhưng khi đo lại, page weight vọt lên 2.1 MB vì họ nhúng một thư viện carousel ảnh 360 độ nặng 600 KB và ba video autoplay. Vì đã có budget rõ ràng từ đầu, cuộc tranh luận không còn là chuyện cảm tính "trang này có chậm không". Nó trở thành một quyết định định lượng: "Chúng ta vượt budget 900 KB. Bỏ carousel 360 độ hay lazy-load video?" Đội chọn lazy-load video và nén ảnh, đưa page weight về 1.15 MB — vẫn trong budget.

Bài học: Budget biến những cuộc tranh cãi chủ quan về hiệu năng thành quyết định kỹ thuật rõ ràng, có con số làm trọng tài. Không có budget, tính năng đẹp luôn thắng hiệu năng — cho đến khi khách hàng bỏ đi vì trang tải chậm.

Ví dụ 2 — SLO và Error Budget tại một ngân hàng số Việt Nam

Một ngân hàng số (giả định là "TNEX") cam kết trong SLA với đối tác rằng API chuyển tiền có uptime 99.9%. Đội SRE nội bộ đặt SLO chặt hơn: 99.95% request chuyển tiền phải thành công và có latency dưới 800ms, đo trên chu kỳ 30 ngày. Error budget tương ứng của SLO này là 0.05%, tức khoảng 21 phút "được phép lỗi" mỗi tháng.

Đầu tháng, một đợt phát hành tính năng mới gây ra vài sự cố timeout, tiêu mất 15 phút error budget chỉ trong tuần đầu. Đội performance ngay lập tức chạy lại load test với threshold trong k6 phản ánh đúng SLO (http_req_duration: p(95)<800, http_req_failed: rate<0.0005). Test cho thấy tầng cache Redis quá tải ở mức 1.500 giao dịch/giây. Vì error budget sắp cạn, quản lý ra quyết định: hoãn phát hành tính năng kế tiếp, dồn sprint tới để nâng cấp tầng cache.

Bài học: Error budget cho đội một cơ chế khách quan để quyết định khi nào ưu tiên ổn định thay vì tính năng mới. Nó biến "hệ thống đang có vẻ hơi chậm" thành "chúng ta còn 6 phút error budget, phải hành động ngay". Và quan trọng: SLO đặt chặt hơn SLA tạo vùng đệm, giúp đội sửa lỗi trước khi vi phạm cam kết pháp lý.

Ví dụ 3 — Startup giao đồ ăn đặt sai SLO

Một startup giao đồ ăn quy mô Đông Nam Á đặt SLO rất tham vọng cho toàn bộ hệ thống: "100% request dưới 200ms". Nghe rất oai. Nhưng khi vận hành thực tế, họ phát hiện SLO này gây hại: mỗi khi có một request lẻ chạm 210ms (do một node bị GC pause vài mili giây), hệ thống cảnh báo báo động đỏ, đội on-call bị đánh thức lúc 3 giờ sáng cho một sự cố chẳng ai nhận ra. Sau ba tuần kiệt sức, đội xem lại và nhận ra sai lầm: đặt SLO ở mức 100% và dùng giá trị tuyệt đối (max) thay vì percentile.

Họ chỉnh lại: "99% request dưới 300ms, 99.9% dưới 800ms, đo ở p95 và p99". Cảnh báo giảm 95%, và những cảnh báo còn lại đều là sự cố thật đáng xử lý.

Bài học: SLO 100% là cái bẫy — nó bất khả thi về mặt vật lý và biến hệ thống cảnh báo thành nguồn gây nhiễu. SLO tốt luôn dùng percentile (p95, p99) và chấp nhận một error budget hợp lý. Mục tiêu của SLO không phải là hoàn hảo, mà là "đủ tốt để người dùng hài lòng và đội không kiệt sức".

Hướng dẫn từng bước

Đây là quy trình thiết lập performance budget và SLO trước một chiến dịch test:

Bước 1 — Xác định user journey quan trọng nhất. Đừng đặt budget cho mọi endpoint. Hãy chọn các luồng sinh ra doanh thu hoặc ảnh hưởng trực tiếp trải nghiệm: đăng nhập, tìm kiếm, thêm giỏ hàng, thanh toán. Với mỗi luồng, xác định các endpoint API tham gia.

Bước 2 — Thu thập baseline hiện tại (nếu hệ thống đã chạy). Chạy một bài load test nhẹ hoặc lấy số liệu từ APM/log production để biết latency, throughput, error rate hiện tại đang ở đâu. SLO nên xuất phát từ thực tế, không phải từ mơ ước. Nếu p95 hiện tại là 600ms, đặt SLO 200ms là phi thực tế cho sprint tới.

Bước 3 — Đặt SLO dựa trên kỳ vọng người dùng, không phải khả năng kỹ thuật. Hỏi: "Người dùng bắt đầu cảm thấy khó chịu ở đâu?" Với web, ngưỡng tâm lý thường là: dưới 1s là "tức thì", 1–3s là "chấp nhận được", trên 3s là "chậm, người dùng bỏ đi". Từ đó suy ra SLO, ví dụ: p95 checkout < 1s, p99 < 2s.

Bước 4 — Chuyển SLO thành percentile cụ thể + cửa sổ thời gian. Một SLO hoàn chỉnh luôn có bốn thành phần: chỉ số (latency/error rate) + ngưỡng + percentile + cửa sổ đo. Ví dụ đầy đủ: "p95 của http_req_duration < 500ms, đo trên cửa sổ trượt 30 ngày."

Bước 5 — Tính error budget. Lấy 100% − SLO để ra lượng lỗi cho phép. SLO 99.9% → error budget 0.1% → ~43 phút/tháng. Ghi con số này ra để cả đội cùng thấy.

Bước 6 — Mã hóa SLO thành Threshold/Assertion trong công cụ test. Đây là bước nối budget với test thực tế. Trong k6:

export const options = {
  thresholds: {
    // SLO: p95 latency < 500ms, p99 < 1s
    http_req_duration: ['p(95)<500', 'p(99)<1000'],
    // Error budget: dưới 0.1% request được phép lỗi
    http_req_failed: ['rate<0.001'],
    // Budget throughput: phải xử lý tối thiểu 300 req/s
    http_reqs: ['rate>300'],
  },
};

Trong JMeter, bạn dùng Duration Assertion cho latency và Response Assertion cho error, kết hợp với các listener tổng hợp percentile. Khi threshold không đạt, k6 trả về exit code khác 0 — điều này rất quan trọng cho bước tiếp theo.

Bước 7 — Gắn vào cổng chất lượng (quality gate). Vì threshold trả exit code khác 0 khi fail, bạn có thể để pipeline tự động chặn việc phát hành khi SLO không đạt. Đây là cách budget/SLO trở thành "người gác cổng" tự động thay vì một tài liệu bị lãng quên.

Bước 8 — Xem lại và điều chỉnh định kỳ. SLO không phải khắc trên đá. Mỗi quý, xem lại: SLO có quá chặt (gây nhiễu cảnh báo) hay quá lỏng (người dùng phàn nàn dù vẫn "đạt")? Điều chỉnh cho khớp thực tế.

Lỗi thường gặp & mẹo

Lỗi 1 — Đặt SLO bằng giá trị trung bình (average/mean). Trung bình che giấu đuôi phân phối. Nếu 90 request là 50ms và 10 request là 5.000ms, trung bình vẫn "đẹp" nhưng 10% người dùng đang chịu trải nghiệm thảm họa. Mẹo: Luôn dùng percentile (p95, p99). Với hệ thống quan trọng, quan tâm cả p99.9.

Lỗi 2 — Đặt SLO 100%. Như ví dụ 3 đã chỉ ra, 100% là bất khả thi và biến cảnh báo thành nguồn nhiễu. Mẹo: Bắt đầu từ 99% hoặc 99.9%, để lại error budget thở được.

Lỗi 3 — Đặt budget/SLO sau khi đã test xong. Nhiều người chạy test trước, thấy kết quả rồi mới đặt ngưỡng vừa khít con số vừa đo. Đây là ngụy biện tự thỏa mãn — bạn chỉ đang hợp thức hóa hiện trạng chứ không đặt mục tiêu. Mẹo: Chốt SLO trước, trên cơ sở kỳ vọng người dùng, rồi mới test.

Lỗi 4 — Một SLO cho tất cả endpoint. Endpoint tìm kiếm và endpoint upload ảnh có đặc tính hoàn toàn khác nhau. Mẹo: Đặt SLO riêng theo nhóm endpoint hoặc theo tag. Trong k6 bạn có thể đặt threshold riêng cho từng tag.

Lỗi 5 — Quên cửa sổ thời gian. "99.9% uptime" mà không nói trong bao lâu thì vô nghĩa. 99.9% mỗi ngày khác hẳn 99.9% mỗi năm. Mẹo: Luôn kèm cửa sổ đo (thường 28–30 ngày cho SLO production).

Mẹo vàng: Viết SLO ra thành tài liệu ngắn gọn mà cả product manager lẫn kỹ sư đều đọc được, không chỉ để trong code. SLO là ngôn ngữ chung giữa kỹ thuật và kinh doanh — đó là sức mạnh lớn nhất của nó.

Bài tập thực hành

  • Thiết lập budget cho một trang thật. Chọn một website Việt Nam bạn hay dùng (Tiki, Shopee, VNExpress). Mở DevTools → tab Network, tải lại trang, và ghi lại: page weight, số request, TTFB. Từ đó, tự đề xuất một performance budget hợp lý cho trang đó với 4 chỉ tiêu cụ thể.
  • Viết SLO đầy đủ 4 thành phần. Cho endpoint /api/search của một sàn thương mại điện tử. Viết 3 SLO hoàn chỉnh (mỗi cái phải có: chỉ số + ngưỡng + percentile + cửa sổ thời gian). Sau đó tính error budget theo phút cho từng SLO.
  • Mã hóa SLO thành k6 threshold. Lấy 3 SLO ở bài 2, viết block thresholds trong options của k6 sao cho test sẽ fail (exit code khác 0) khi bất kỳ SLO nào không đạt.
  • Phân tích error budget. Một dịch vụ có SLO 99.5% thành công/tháng. Trong 20 ngày đầu tháng đã tiêu hết 80% error budget. Bạn là performance engineer — hãy viết một khuyến nghị 3–4 câu cho quản lý về việc nên làm gì trong 10 ngày còn lại và giải thích lý do dựa trên khái niệm error budget.
  • Sửa SLO tồi. Cho SLO sau: "Response time trung bình phải nhỏ hơn 500ms, 100% thời gian." Chỉ ra 2 điểm sai và viết lại thành một SLO tốt.

Tóm tắt

Performance testing chỉ có ý nghĩa khi bạn biết trước "thế nào là đạt" — và đó chính là việc của Performance Budget và SLO.

  • Performance Budget là các giới hạn định lượng (page weight, latency, số request, throughput) đặt ra ngay từ giai đoạn thiết kế, biến tranh luận cảm tính về hiệu năng thành quyết định có con số làm trọng tài.
  • SLI / SLO / SLA là bộ ba cần phân biệt rõ: SLI là điều bạn đo, SLO là mục tiêu bạn nhắm tới, SLA là cam kết pháp lý bạn hứa. SLO nên đặt chặt hơn SLA để có vùng đệm.
  • Error Budget (100% − SLO) biến mục tiêu trừu tượng thành lượng lỗi cho phép cụ thể (ví dụ 43 phút/tháng), là công cụ khách quan để cân bằng giữa ra tính năng mới và giữ ổn định.
  • SLO tốt luôn dùng percentile (không dùng trung bình), không đặt 100%, và luôn kèm cửa sổ thời gian.
  • Cuối cùng, SLO chính là hiện thân của các Threshold (k6) và Assertion (JMeter) mà bạn viết trong bài test. Chốt SLO trước, rồi mới test — đó là dấu hiệu của một performance engineer thực thụ, không phải người chỉ biết chạy tool.
Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi