Chương 84. Checklist production
Chương trước nói về checklist thiết kế.
Checklist thiết kế giúp ta hỏi:
Request đi qua đâu?
Dữ liệu nằm ở đâu?
Transaction kết thúc ở đâu?
Job retry thế nào?
Cache có sai không?
Ai được quyền làm gì?
Quan sát bằng gì?
Chi phí phình ở đâu?
Chương này nói về một câu hỏi khác:
Hệ thống này đã sẵn sàng chạy production chưa?
Production không giống môi trường dev.
Production có:
User thật.
Dữ liệu thật.
Tiền thật.
Deadline thật.
Traffic thật.
Bug thật.
Provider thật.
Support thật.
Uy tín thật.
Một hệ thống chạy được trên máy dev chưa chắc đã production-ready.
Thông điệp chính của chương:
> Production readiness không phải là hệ thống không bao giờ lỗi. Nó là việc hệ thống có timeout, retry đúng, idempotency, rate limit, logs, metrics, alerts, backup, rollback, load test và tài liệu vừa đủ để khi lỗi xảy ra, team phát hiện được, giới hạn được và phục hồi được.
---
84.1. Một tình huống: demo chạy tốt, production đau
Hãy quay lại AI Judge.
Trong demo:
Một học sinh nộp bài.
AI chấm xong.
Giáo viên thấy điểm.
Mọi thứ đẹp.
Nhưng khi production:
5.000 học sinh nộp trong 10 phút.
AI provider timeout.
Worker retry liên tục.
Queue backlog.
Một số job chạy hai lần.
Credit bị trừ hai lần.
Không có alert queue age.
Không biết prompt version nào gây lỗi.
Rollback prompt mới phải sửa config thủ công.
Backup có nhưng chưa từng restore.
Demo chứng minh luồng happy path tồn tại.
Production readiness chứng minh hệ thống chịu được đời thật.
Chương này là danh sách các câu hỏi cần trả lời trước khi nói:
Ổn, có thể chạy cho user thật.
---
84.2. Timeout
Timeout là giới hạn thời gian chờ.
Không có timeout nghĩa là một thao tác có thể treo rất lâu.
Câu hỏi:
Mọi call qua network có timeout không?
Database query có timeout không?
AI provider call có timeout không?
Webhook call có timeout không?
File scan/convert có timeout không?
Job có max runtime không?
Ví dụ AI call:
Provider không trả lời.
Worker chờ mãi.
Worker slot bị giữ.
Queue backlog tăng.
Timeout bảo vệ tài nguyên.
Nhưng timeout phải hợp lý.
Quá ngắn:
Request bình thường bị fail giả.
Retry tăng.
Quá dài:
Tài nguyên bị giữ lâu.
Queue chậm.
Timeout nên dựa trên latency thực tế và SLO.
Không nên để default vô hạn.
---
84.3. Retry
Retry giúp hệ thống vượt qua lỗi tạm thời.
Nhưng retry sai có thể tạo sự cố lớn.
Câu hỏi:
Lỗi nào được retry?
Lỗi nào không retry?
Retry tối đa bao nhiêu lần?
Có backoff không?
Có jitter không?
Retry có làm double side effect không?
Ví dụ nên retry:
Timeout.
HTTP 429.
HTTP 500/502/503/504.
Network error.
Ví dụ không nên retry:
Input invalid.
Unauthorized.
Permission denied.
API key sai.
Submission không tồn tại.
Với AI Judge, nếu AI trả JSON sai format, có thể retry một lần với prompt sửa format.
Nhưng nếu bài thiếu file, retry vô hạn không giúp gì.
Retry phải có giới hạn.
Retry không phải hy vọng.
Retry là chính sách.
---
84.4. Idempotency
Idempotency nghĩa là cùng một hành động lặp lại không tạo hậu quả trùng.
Production sẽ có lặp:
User bấm lại.
Frontend retry.
Webhook gửi lại.
Queue message redeliver.
Worker crash trước khi ack.
Network timeout.
Câu hỏi:
Submit retry có tạo hai submission không?
Job chấm retry có tạo hai kết quả chính thức không?
Payment webhook duplicate có cộng credit hai lần không?
Notification retry có gửi hai email không?
LMS sync retry có tạo record trùng không?
Idempotency cần key rõ:
client_request_id.
external_id.
provider_event_id.
submission_attempt_id.
ledger idempotency key.
Nếu một luồng production quan trọng không idempotent, retry trở thành nguy hiểm.
Không có idempotency, reliability và correctness đánh nhau.
---
84.5. Rate limit
Rate limit bảo vệ hệ thống khỏi traffic quá mức.
Câu hỏi:
Endpoint nào cần rate limit?
Theo user, tenant, IP, API key hay resource?
Rate limit response có rõ không?
Có Retry-After không?
Có quota theo plan không?
Có limit cho AI cost không?
Với AI Judge:
Submit bài.
Regrade.
Bulk import.
Search.
File upload.
AI grading.
Partner API.
Login.
đều có thể cần giới hạn khác nhau.
Rate limit không chỉ chống abuse.
Nó còn chống bug.
Một script tích hợp sai có thể gọi API hàng nghìn lần/phút.
Rate limit giúp lỗi đó không kéo sập toàn hệ thống.
---
84.6. Logs
Logs giúp trả lời:
Chuyện gì đã xảy ra?
Production logs nên có cấu trúc.
Câu hỏi:
Log có request_id không?
Có tenant_id không?
Có user_id nếu phù hợp không?
Có job_id không?
Có provider/model/prompt version không?
Error có stack/context không?
Log có chứa PII/secret quá mức không?
Với AI Judge, khi một bài chấm lỗi, log nên giúp biết:
submission_id.
tenant_id.
grading_job_id.
prompt_version.
model/provider.
attempt number.
error class.
duration.
Không nên log:
API key.
Secret.
Full prompt/response nhạy cảm vào log chung.
Logs phải đủ để debug.
Nhưng không được biến thành nơi rò dữ liệu.
---
84.7. Metrics
Metrics giúp trả lời:
Hệ thống đang khỏe hay yếu?
Câu hỏi:
Có metric cho request rate không?
Latency p95/p99 không?
Error rate không?
Queue length và oldest job age không?
Worker throughput không?
Provider latency/error/429 không?
Database latency không?
Cost/token không?
Với AI Judge, các metric quan trọng:
submit_success_rate.
submit_latency.
time_to_grade.
oldest_grading_job_age.
grading_failure_rate.
provider_timeout_rate.
retry_rate.
parse_error_rate.
needs_review_rate.
cost_per_submission.
Metrics nên đo triệu chứng user thấy.
Không chỉ đo CPU.
CPU cao mà user không bị ảnh hưởng có thể chưa critical.
Bài chấm chậm vượt SLO mới là vấn đề thật.
---
84.8. Alerts
Alert trả lời:
Khi nào cần gọi người xử lý?
Câu hỏi:
Alert có actionable không?
Có owner không?
Có severity không?
Có runbook không?
Có gắn SLO không?
Có quá nhiễu không?
Alert kém:
CPU > 80% trong 1 phút.
Alert tốt hơn:
95% submissions không được chấm trong 30 phút.
Oldest grading job age > 20 phút.
Provider timeout rate > 20% trong 10 phút.
Payment succeeded nhưng credits chưa grant sau 10 phút.
Alert tốt nói về ảnh hưởng thật.
Không nên alert mọi lỗi lẻ.
Một job fail có thể chỉ cần log/metric.
Tỉ lệ job fail cao mới cần alert.
---
84.9. Backup
Backup trả lời:
Nếu dữ liệu mất/hỏng, ta cứu thế nào?
Câu hỏi:
Dữ liệu nào được backup?
Database có PITR không?
Object storage có versioning/replication không?
Backup retention bao lâu?
Backup có mã hóa không?
Backup có nằm tách production không?
Backup fail có alert không?
Đã test restore chưa?
Với AI Judge, dữ liệu quan trọng:
Submission gốc.
File bài làm.
Rubric.
Grading result.
Teacher review.
Audit log.
Ledger/usage.
Tenant config.
Backup chưa test restore thì chưa đáng tin.
Production-ready nghĩa là không chỉ có file backup.
Mà là có quy trình khôi phục đã thử.
---
84.10. Rollback
Rollback trả lời:
Nếu deploy lỗi, quay lại thế nào?
Câu hỏi:
Rollback code mất bao lâu?
Feature flag có tắt được không?
Prompt/model có quay lại version cũ không?
Migration có backward-compatible không?
Code cũ đọc được dữ liệu mới không?
Rollback có cần data rollback không?
Ai có quyền rollback?
Rollback code thường dễ hơn rollback dữ liệu.
Vì vậy migration phải cẩn thận.
Pattern an toàn:
Expand.
Deploy code đọc/ghi cả cũ và mới.
Backfill.
Switch read.
Contract/dọn sau.
Không nên deploy thay đổi dữ liệu phá backward compatibility mà không có đường quay lại.
Nếu không thể rollback, phải có roll-forward plan rất rõ.
---
84.11. Load test
Load test trả lời:
Hệ thống chịu được tải dự kiến không?
Câu hỏi:
Đã test peak request chưa?
Đã test upload peak chưa?
Đã test queue backlog chưa?
Đã test worker throughput chưa?
Đã test provider limit bằng mock/fake chưa?
Đã test database query nặng chưa?
Đã test graceful degradation chưa?
Load test không cần mô phỏng toàn bộ thế giới ngay.
Nhưng nên test luồng sống còn:
Nộp bài.
Upload file.
Tạo job chấm.
Worker xử lý job.
Dashboard đọc trạng thái.
Với AI provider thật, không nên load test bừa gây tốn tiền hoặc vi phạm quota.
Có thể dùng fake provider có latency giống thật.
Mục tiêu là biết hệ thống của mình nghẽn ở đâu.
---
84.12. Capacity
Capacity là khả năng xử lý của hệ thống.
Câu hỏi:
API chịu được bao nhiêu RPS?
Worker xử lý bao nhiêu job/phút?
Queue backlog tối đa chấp nhận bao nhiêu?
Database connection pool đủ không?
Object storage/upload path đủ không?
Provider ngoài giới hạn bao nhiêu?
Production-ready không có nghĩa capacity vô hạn.
Nó nghĩa là team biết giới hạn hiện tại.
Ví dụ:
Với cấu hình hiện tại, hệ thống xử lý ổn 300 submissions/phút.
Nếu vượt 500 submissions/phút, queue age tăng.
Nếu AI provider timeout > 20%, grading SLO sẽ bị vi phạm.
Biết giới hạn giúp ta:
Đặt rate limit.
Đặt alert.
Nói thật với business.
Chuẩn bị scale.
Không biết giới hạn là rủi ro.
---
84.13. Secrets
Secrets là thông tin nhạy cảm như:
Database password.
API key.
Model provider key.
Webhook secret.
Encryption key.
OAuth secret.
Câu hỏi:
Secret có nằm trong repo không?
Secret có nằm trong log không?
Secret có rotation không?
Ai được đọc secret?
Production và staging có tách secret không?
Agent/model có nhìn thấy secret không?
Production-ready nghĩa là secret được quản lý đúng.
Không dùng:
.env copy qua chat.
Hardcode API key.
Log full header Authorization.
Secret nên nằm trong secret manager hoặc cơ chế bảo vệ phù hợp.
Nếu một key bị lộ, phải có cách rotate và revoke.
---
84.14. Health check
Health check giúp hệ thống biết instance có sống và sẵn sàng nhận traffic không.
Câu hỏi:
Liveness check có không?
Readiness check có không?
Worker health có không?
Queue connection có kiểm tra không?
Database connection có kiểm tra không?
Health check có quá nặng không?
Liveness:
Process còn sống không?
Readiness:
Service đã sẵn sàng nhận traffic chưa?
Ví dụ API chưa load config hoặc chưa kết nối database thì chưa ready.
Worker không kết nối được queue thì không healthy.
Health check kém có thể làm load balancer gửi traffic vào instance chưa sẵn sàng.
Hoặc ngược lại, health check quá nhạy làm instance restart liên tục.
---
84.15. Documentation vừa đủ
Documentation production không cần dài.
Nhưng phải đủ để người trực xử lý.
Cần có:
Hệ thống gồm các thành phần nào?
Luồng request/job chính là gì?
Dashboard ở đâu?
Alert nghĩa là gì?
Runbook xử lý alert chính.
Cách rollback.
Cách restore.
Cách rotate secret.
Cách tạm tắt feature nguy hiểm.
Với AI Judge:
Runbook queue backlog.
Runbook provider outage.
Runbook prompt rollback.
Runbook payment/credit mismatch.
Runbook file upload/scan failure.
Tài liệu vừa đủ là tài liệu dùng được lúc căng thẳng.
Không cần văn chương.
Cần rõ, ngắn, đúng và cập nhật.
---
84.16. Runbook
Runbook là hướng dẫn xử lý sự cố cụ thể.
Một runbook tốt trả lời:
Alert này nghĩa là gì?
Ảnh hưởng user là gì?
Kiểm tra dashboard nào?
Lệnh/thao tác nào an toàn?
Khi nào rollback?
Khi nào escalate?
Sau khi xử lý cần ghi gì?
Ví dụ runbook queue backlog:
1. Kiểm tra oldest job age.
2. Kiểm tra enqueue rate vs processing rate.
3. Kiểm tra provider latency/timeout.
4. Kiểm tra worker error/retry.
5. Kiểm tra deploy gần nhất.
6. Nếu provider lỗi, mở circuit breaker/tạm giảm traffic.
7. Nếu prompt mới gây latency, rollback flag.
8. Thông báo support nếu user bị ảnh hưởng.
Runbook giúp người trực không phải nghĩ từ số không.
Production-ready nên có runbook cho các sự cố chính.
---
84.17. Production checklist cho AI Judge
Trước khi AI Judge chạy cho user thật, nên hỏi:
Timeout:
AI call, database, file scan, webhook, LMS sync đều có timeout chưa?
Retry:
Retry có backoff/jitter/limit chưa?
Lỗi invalid có bị retry vô hạn không?
Idempotency:
Submit, grading job, credit charge, webhook đều idempotent chưa?
Rate limit:
Submit, regrade, upload, AI call, partner API có giới hạn chưa?
Logs/metrics:
Có request_id, tenant_id, job_id, prompt_version, provider metrics chưa?
Alerts:
Có alert oldest job age, provider timeout, cost spike, payment mismatch chưa?
Backup:
Submission/file/result/audit/ledger backup và test restore chưa?
Rollback:
Prompt/model/code/migration có đường quay lại chưa?
Load test:
Đã test deadline peak và queue backlog chưa?
Docs:
Runbook chính có chưa?
Nếu chưa, hệ thống có thể vẫn chạy.
Nhưng chưa nên tự tin.
---
84.18. Đừng đợi hoàn hảo mới production
Production readiness không có nghĩa hoàn hảo.
Nếu đợi hoàn hảo, ta sẽ không bao giờ launch.
Nhưng cũng không nên launch mù.
Cách thực dụng:
Luồng chính phải an toàn.
Dữ liệu quan trọng phải được bảo vệ.
Lỗi quan trọng phải thấy được.
Rollback/restore phải có đường.
Rủi ro còn lại phải được biết và chấp nhận.
Ví dụ có thể chấp nhận:
Dashboard realtime chưa có, dùng polling.
Advanced analytics chưa có.
Một số alert chưa tối ưu.
Khó chấp nhận:
Không backup submission.
Không biết job chấm đang backlog.
AI retry có thể trừ credit hai lần.
Không có cách rollback prompt mới.
Secret nằm trong repo.
Production readiness là quản lý rủi ro, không phải đạt điểm 100.
---
84.19. Checklist production tổng hợp
Timeout:
- Mọi network call có timeout không?
- Job có max runtime không?
Retry:
- Retry có limit, backoff, jitter không?
- Lỗi vĩnh viễn có bị retry vô hạn không?
Idempotency:
- Request/job/webhook/payment/charge có idempotency không?
Rate limit:
- Endpoint nặng, AI call, upload, login, partner API có giới hạn không?
Logs:
- Log có cấu trúc và correlation id không?
- Log có tránh PII/secret quá mức không?
Metrics:
- Có đo latency, error, throughput, queue age, provider, cost không?
Alerts:
- Alert có actionable, owner, severity, runbook không?
Backup:
- Backup có chạy không?
- Đã test restore chưa?
Rollback:
- Code/config/prompt/model/migration có đường quay lại không?
Load test:
- Đã test luồng chính ở peak chưa?
- Đã biết bottleneck chưa?
Secrets:
- Secret có quản lý đúng, rotate/revoke được không?
Health check:
- Liveness/readiness/worker health có ý nghĩa không?
Documentation:
- Có runbook cho sự cố chính không?
- Tài liệu có đủ để người khác vận hành không?
---
84.20. Kết luận của chương
Production không yêu cầu hệ thống không bao giờ lỗi.
Production yêu cầu hệ thống biết lỗi trong giới hạn có thể quản lý.
Timeout giúp không treo vô hạn.
Retry giúp vượt lỗi tạm thời, nhưng phải có idempotency.
Rate limit bảo vệ tài nguyên.
Logs, metrics và alerts giúp thấy vấn đề.
Backup và restore giúp cứu dữ liệu.
Rollback giúp giảm thiệt hại khi deploy sai.
Load test giúp biết giới hạn.
Secrets và health check giúp vận hành an toàn.
Documentation và runbook giúp con người xử lý khi hệ thống đau.
Thông điệp cần nhớ:
> Production-ready không phải là chạy được một lần. Production-ready là khi hệ thống có đủ cơ chế để được quan sát, giới hạn, phục hồi và vận hành bởi con người khi đời thật không đi theo happy path.
Ở chương tiếp theo, ta sẽ nói về những lỗi kiến trúc phổ biến: over-engineering, under-engineering, thiếu ownership, thiếu source of truth, cache sai, async sai, microservices quá sớm, và nhiều kiểu bẫy mà hệ thống thật hay gặp.