CI và build ở quy mô lớn
Bài toán
Lúc nhỏ, CI là "mỗi commit chạy hết build và test". Khi codebase và số commit tăng, chạy hết trở thành bất khả (Stripe 2026: chạy tuần tự mất bốn tháng), và thời gian chờ của một thay đổi không còn chỉ là thời gian build của nó: còn là thời gian dựng môi trường (checkout repo lớn, kéo image), thời gian chờ sau những thay đổi xung đột phía trước trong hàng đợi merge, và độ tin cậy của chính hệ CI (phụ thuộc hàng chục dịch vụ). Bài toán ở đây là chỉ làm phần việc mà thay đổi thật sự ảnh hưởng, và làm phần đó ở chỗ đã có sẵn trạng thái: biết cái gì bị ảnh hưởng, chia việc cho nhiều máy mà không lặp, và dùng lại kết quả giữa các máy, các lần chạy, giữa lúc review và lúc merge.
Trang này nói về kiểm chứng thay đổi trước khi merge (build, test, hàng đợi merge, hạ tầng runner). Đưa thay đổi lên production (canary, rollout, rollback) nằm ở Deploy và release an toàn; thay đổi hàng loạt trên nhiều repo nằm ở Quản lý fleet và migrate code hàng loạt.
Diễn tiến theo thời gian
- 2012→2025 · Jane Street: tự viết Jenga (2012), mở mã nguồn nhưng không ai dùng; Jbuilder (2016) chỉ là shim nhưng nhanh hơn OCamlbuild 5 lần nên thành Dune; hai build system song song nhiều năm. Khi đội build đủ 5 người mới chuyển repo 70 triệu dòng sang Dune (hơn một năm); build gần như toàn cache nhanh 2–3 lần. Jane Street 2025
- 2014 · Jane Street: build-bot test trước khi tích hợp ("not rocket science rule") nhưng tuần tự: build cả cây trên 2 giờ, có thay đổi chờ 24 giờ. Đầu cơ song song, gộp lô, build incremental (Jenga), đổi quy trình review (repo chính từ hàng trăm xuống 30–40 request/tuần), rồi release phân cấp trong Iron. Jane Street 2014
- 2016→2024 · GitHub: deploy trước merge; "train" gom tới 15 PR do một người điều phối hay trật bánh (có lần chờ hơn 8 giờ rồi bị loại vì xung đột). Thay bằng merge queue tự gom nhóm động, tự loại PR xung đột, ưu tiên throughput toàn hệ hơn công bằng từng PR; chuyển dần 2021–2023. 500 engineer, 2.500 PR/tháng vào monorepo, nhóm 30 PR trở lên, thời gian chờ trung bình −33%. GitHub 2024
- 2016 · Riot Games: League client update nhận build mỗi 15 phút; test hỏng phải điều tra ngay, test không ổn định và test mới ở staging suite ngoài pipeline; mỗi plugin mới ghép với bản Last Known Good của mọi plugin khác để chạy functional test giới hạn; test chuyển về repo của plugin. Riot Games 2016
- 2016 · Stack Overflow: GitLab và TeamCity on-prem để build không phụ thuộc Internet; build agent chạy ngay trên 11 web server (dư CPU), poll repo mỗi 15 giây, git mirror trên agent; gần như mọi commit vào thẳng master. Stack Overflow 2016
- 2016→2017 · Zillow: tách repo static-all: build 30 → 8 phút, người commit mỗi tháng 75 → 3; test tự động qua loader bắt module trùng, thiếu phụ thuộc và phụ thuộc vòng giữa các bundle mới. Zillow 2017
- 2016→2017 · Zillow: mỗi push đo kích thước bundle webpack, đẩy vào Splunk, có ngưỡng làm vỡ build; ngưỡng bắt được hai major version React cùng nằm trong bundle; thêm bước fail build khi một package có nhiều version. Zillow 2017
- 2017 · Yahoo: Screwdriver, hệ build/CD dùng chung toàn công ty khoảng 5 năm, hơn 25.000 build/ngày và 12.000 commit/ngày. Pipeline cấu hình trong repo (self-service, review được), môi trường tạm cho mỗi PR để chạy test chức năng; ban đầu là lớp trên Jenkins, vượt một cụm thì lập lịch qua nhiều cụm rồi bỏ dần Jenkins. Yahoo 2017
- 2018 · Facebook (Meta): chọn test theo phụ thuộc build chọn tới một phần tư toàn bộ test cho mỗi thay đổi mobile; thay bằng predictive test selection (gradient-boosted tree học từ lịch sử, retry mạnh tay để tách test flaky khỏi dữ liệu huấn luyện). Ngưỡng ở production: bắt ít nhất một test fail cho hơn 99,9% thay đổi lỗi. Kết quả: bắt hơn 99,9% hồi quy trong khi chỉ chạy khoảng một phần ba số test phụ thuộc bắc cầu. Meta 2018
- 2018 · LinkedIn: hơn 10.000 multiproduct phụ thuộc nhau qua artifact nhị phân; service phụ thuộc mới ghi đồ thị đã giải ở mức module lấy từ chính Gradle, nhập gần realtime theo event publish của Artifactory; báo nhầm phụ thuộc vòng giảm 60%. LinkedIn 2018
- 2018 · Jane Street: môi trường Python Conda dùng chung trên NFS (khởi động vài phút, không tái lập) → XAR một file, build trong CI bằng build system chính, liên kết tĩnh thư viện nội bộ và binding OCaml, tag nightly/stable (bài 2023). Jane Street 2023
- 2019 · SoundCloud: remote build cache của Gradle bật rồi mà gần như không trúng: hằng số BuildConfig khác giữa CI và local, CI tắt incremental compile của Kotlin, thư mục rỗng, file sinh ra chứa đường dẫn tuyệt đối, Instant Run tắt cache. Ép đồng nhất bằng cách làm build fail kèm hướng dẫn sửa; build trung bình từ 49,55 xuống 36,84 giây, mỗi developer khoảng 40 build/ngày. SoundCloud 2019 SoundCloud 2019
- 2019 · Appian: test Jepsen chạy thành job Jenkins trên
master(tham số phiên bản, thời lượng, số node); script chờ mọi container healthy; kết quả chia vi phạm / đúng / test hỏng để biết sửa hệ hay sửa test. Appian 2019 - 2019 · Bumble (Badoo): 100.000 unit, 6.000 integration, 14.000 API test (chạy một luồng khoảng 12 giờ) xuống dưới 22 phút: cloud chạy test, chunk khoảng 30 giây theo thời gian đo được, chừa một phần cloud cho test nhanh; chọn test theo coverage thu mỗi ngày, nhưng build phát hành vẫn chạy hết vì coverage lệch một build. Bumble 2019
- 2019 · Slalom Build (bài quan điểm): đưa mọi test tự động vào pipeline chứ không chỉ unit test; rào cản thường là khả thi nhỏ (runner không có browser, không chạy được service trong process, DB khó giả) chứ không phải chi phí, vì runner sẵn có còn dư capacity Slalom Build 2019
- 2020 · Airbnb: khi chuyển sang SOA, project "deep integration test" chạy mọi test của mọi service trước khi merge thì chậm và flaky dần theo số service. Tách: CI chỉ chạy unit test và shallow integration test của một service (phụ thuộc mock bằng fixture), test sâu chuyển sang bước CD trên staging + canary analysis. Theo Airbnb: đẩy test xuống tầng thấp nhất có thể. Airbnb 2020
- 2020 · Hotstar: agent CI cũ phần lớn thời gian ngồi không; chuyển sang elastic agent là pod Kubernetes, bật khi có job, init-container lấy credential từ Vault theo profile; pipeline là YAML trong git, kiểm bằng API preflight vì một cấu hình sai chặn mọi thay đổi sau. Disney Hotstar 2020
- 2020 · Wix: từ một server TeamCity cho 5 monolith và khoảng 50 developer (khoảng 2011) lên khoảng 1.000 developer, hàng nghìn artifact: cổng Lifecycle ghép dữ liệu build server, Artifactory, production và monitoring; các service nghe event commit/build qua Kafka để dựng thực thể artifact chung. Wix 2020
- 2020 · Rust: giữ master luôn xanh bằng cách test và merge từng PR một (bors); 57 builder mỗi lượt 3–4 giờ trên VM 2 core nên PR chờ nhiều ngày. Chuyển sang GitHub Actions với VM 8 core được tài trợ để rút ngắn lượt chạy. Rust 2020
- 2020 · Atlassian: CI cho infrastructure as code: mỗi commit dựng một cụm Kubernetes thật rồi phá bỏ; khó nhất là phá bỏ đáng tin (aws-nuke thay
terraform destroy), thêmsleep2 phút vì IAM policy tạo lại chậm có hiệu lực, giới hạn song song do gateway mạng cấp tay nên dựng sẵn nhiều môi trường. Atlassian 2020 - 2020 · Trendyol: stage Test mới trong GitLab CI chạy
docker-compose up --build(service, DB, mock API ngoài, container test) trên mỗi push Trendyol 2020 - 2020 · LinkedIn:
git submitchạy validation rồi tự rebase và push hộ dev; mỗi repo chọn pre/post-merge theo tốc độ commit (repo bận chạy cả hai để bắt soft conflict), "ai xong trước vào trước" thay FIFO; repo bận nhất (hơn 300 commit/ngày) chỉ khoảng 5 soft conflict/năm. LinkedIn 2020 - 2021 · Riot Games: monorepo 100 GB, khoảng 100 lượt pipeline đầy đủ mỗi ngày, mỗi lượt 60 phút. Build plan bằng hash để chỉ build artifact đổi; hai loại build (thử nhanh trên một nền tảng nhưng commit status vẫn báo thất bại, và build đầy đủ bắt buộc trước merge); đồng bộ workspace qua patcher của game (10–15 giây thay vì 1–2 phút). Pipeline phụ thuộc khoảng 50 dịch vụ, nên chỉ tin cậy khoảng 60% nếu mỗi dịch vụ 99%. Riot Games 2021
- 2021→2022 · Uber: monorepo Go hơn 10 triệu target, khoảng 50 thay đổi/giờ; thay đổi ảnh hưởng hơn 10.000 target chặn cả SubmitQueue hàng giờ. Đi từ chặn big change giờ cao điểm (vá tạm) → 50 shard tĩnh trên Jenkins → shard theo root target (bỏ được lệnh chặn) → Buildkite động (trung vị tệ đi vì mỗi shard checkout lại repo, chữa bằng snapshot Git, container sống lâu, cache trên host) → remote cache artifact và kết quả test trên Buildfarm (build giảm khoảng một nửa). Thay đổi ảnh hưởng toàn repo land dưới 15 phút. Uber 2022
- 2021 · Pinterest: monorepo Java Optimus (hơn 120 service, 300 người đóng góp/tháng): build-collector dùng Bazel query
rdepsđể chỉ chạy target bị ảnh hưởng, file BUILD là hợp đồng giữa CI và developer, release rule tự viết che hạ tầng phát hành, target chạy song song trên nhiều worker. P50 từ 52 xuống 19 phút, P90 từ 69 xuống 49 phút (đo trong 2020). Pinterest 2021 - 2021 · Grammarly: build iOS/macOS trên dàn máy Apple ở văn phòng (phải VPN từ San Francisco sang Kyiv) chuyển lên EC2 Mac: AMI bằng Ansible + Packer, runner tự đăng ký vào GitLab lúc khởi động. EC2 Mac 2021 khởi động 5–7 phút, dọn host 60–120 phút, không Auto Scaling, nên co giãn chỉ là thêm máy, không phải theo job. Grammarly 2021
- 2021 · Stack Overflow (bài quan điểm): theo tác giả, ngành chỉ làm CI mà bỏ CD; chỉ số cần đo là thời gian từ merge tới production (khoảng 15 phút là tốt), không chỉ thời gian build. Stack Overflow 2021
- 2021 · Trendyol: mutation testing (PIT) chỉ trên class thêm mới hoặc sửa trong nhánh (
scmMutationCoverageso vớidevelop), kết quả vào SonarQube để quality gate sẵn có chặn pipeline; bản đầy đủ chỉ chạy khi đẩy nhánhpitest-*hoặc local. Trên code đã đổi: 2 phút 44 giây và 15 giây cho hai codebase; giữ một thread vì 4 thread cần heap 4.096 MB;maxDependencyDistance = 1cắt nhiều thời gian. Trendyol 2021 - 2021 · HRT: CI cho phần cứng: license simulator thương mại là trần số test; chuyển sang Verilator (mở) để mỗi developer chạy hàng nghìn mô phỏng, CI thử seed ngẫu nhiên mới và chạy test trong lab Hudson River Trading 2021; năm 2026 cùng một test chạy trên cả Verilator (CI song song) lẫn simulator thương mại (debug nhanh) bằng một cờ dòng lệnh Hudson River Trading 2026.
- 2022 · Grab: repo pipeline ML có file GitLab CI 1.800 dòng (sinh trước rồi commit, chạm giới hạn số
includevà kích thước). Chuyển sang dynamic child pipeline: job đầu tiên đọcgit diff, trích pipeline/stage từ đường dẫn, sinh YAML lúc chạy; file gốc giữ cố định 50 dòng. Grab 2022 - 2022→2023 · Grab: UITest iOS chập chờn sau khi nâng Xcode 13.1: gắn công cụ quan sát vào CI; dời Spotlight (CPU −50%), trình duyệt giả cho test deep link (CI −20%), simulator cấp quyền sẵn, ghi mọi URL để bắt test còn gọi Internet thật; đổi chính sách cho merge nếu lần chạy lại qua. Grab 2023
- 2023 · trivago: kết quả test e2e đẩy lên Kafka → ELK kèm link report lưu trên GCS; Grafana báo khi một kịch bản hỏng trên nhiều nhánh/PR cùng lúc (lỗi chung hoặc flaky, không phải lỗi của PR); test Selenium qua hơn 99%. trivago 2023
- 2023 · HRT: tangle trong codebase Python làm lint/mypy chậm tới mức vô dụng và thay đổi đắt để test; luật phụ thuộc giữa các tầng được kiểm trong CI. Hudson River Trading 2023
- 2024 · Dagger (nhà cung cấp): runner CI chọn phiên bản engine qua
runs-on; Argo CD sinh runner + engine + node pool cho mỗi release, node riêng theo phiên bản; scale ngang (engine tạm) thay vì dọc (engine lớn sống lâu có cache bền), bù bằng một engine dùng chung cache cho nhiều runner trên máy NVMe lớn. Dagger 2024 - 2024 · Uber: SubmitQueue (main luôn xanh cho hơn 4.500 kỹ sư) huỷ 40–65% build suy đoán khi dự đoán đổi, và thay đổi nhỏ phải chờ thay đổi lớn xung đột phía trước. Mô hình mới ưu tiên đều các build cần để thay đổi nhỏ vượt thay đổi lớn khi thứ tự là giao hoán (BLRD), dự đoán thời gian build bằng NGBoost: tài nguyên CI −53%, P95 thời gian chờ −37% trên ba monorepo. Theo Uber, AI làm tốc độ commit tăng sẽ đẩy bài toán xa hơn. Uber 2025
- 2024 · Reddit: flaky test trên project iOS (hơn 20.000 test unit/snapshot, 2.500 UI test): retry 3 lần che triệu chứng, nên ghi từng lần chạy vào Test Metrics Database, nhận diện bằng SQL (khác kết quả trên cùng commit, hỏng trên main), tự mở PR đưa test vào danh sách skip của Bazel và ticket cho team sở hữu; 6 tháng sau số lần chạy flaky giảm 65,7%. Reddit 2024
- 2025 · Notion: ratchet cho lint: baseline số lỗi theo file và rule, CI chặn lỗi mới, pre-commit tự hạ hạn mức khi sửa bớt; ratchet file TSV để sửa song song không xung đột merge. Notion 2025
- 2025 · Railway: builder cho khách (Nixpacks, 14 triệu app) bị mất cache vì deployment ID tiêm vào mọi build làm invalidate mọi layer sau nó; Railpack dựng đồ thị BuildKit LLB, mỗi bước khai báo đầu vào, băm đúng các biến mà bước đó dùng, khoá phụ thuộc của lần build thành công. Image nhỏ hơn 38–77% (theo Railway). Railway 2025
- 2025→2026 · Mercari: runner tạm làm mất cache Turborepo; chạy server remote cache ngay trong job (action nền hoặc sidecar) thay vì service trên GKE ở Nhật (phí truyền 0,08 USD/GiB) hay nhiều instance Cloud Run. Repo module hoá tốt: task Turbo −50%, job −30%; repo một ứng dụng lớn gần như không lợi; server khởi động 10 giây ăn mất lợi ích với task ngắn. Mercari 2026
- 2025 · Rust: đổi trình tự bootstrap: thay vì dựng std stage 0 từ mã nguồn trong cây bằng compiler beta (std phải dựng được bằng hai compiler, đầy
cfg(bootstrap)), tải cả rustc beta lẫn std beta dựng sẵn; std dựng sau compiler nên crate compiler không đổi được cache khi rebase, chỉ dựng lại hết khi bump bootstrap mỗi 6 tuần; sửa std không còn kéo theo dựng lại compiler; profile thư viện tải rustc dựng sẵn từ CI khi compiler không đổi. Rust (Rust Foundation) 2025 - 2025 · Mercari: E2E test trên CI chạy trong Kubernetes không qua image:
go test -cbiên dịch test thành binary, chuyển cùng binary server vào Pod bằngkubectl exec, khoảng 1 phút rưỡi từ build tới lúc test chạy; Kubernetes vì mỗi luồng song song cần một server riêng. Phía iOS: repo app Nhật thành monorepo nhiều sản phẩm trên Bazel (hơn 900 module, remote cache, RBE sẵn có), sinh project Xcode "chứa tất cả" chậm nên cho chọn phạm vi target. Mercari 2025 Mercari 2025 - 2025 · Man Group: profile pip trên Torch, Plotly, Jupyter: lỗi bậc hai khi in tóm tắt (khoảng 30% thời gian với 300 gói), tạo lại thư mục cho từng file, chunk tải 10 KB, thanh tiến trình chiếm 30%, cache requirement quá nhỏ. Gửi PR upstream: install nhanh gấp đôi, download gấp 7, CPU giảm 3 lần; chi phí CI/CD giảm. Man Group 2025
- 2026 · Mercari: runner GitHub Actions tạm trên GKE kéo image 2,4 GiB mỗi job (2–3 phút trên 6–7 phút). Đo ra tải chỉ chiếm 20%, còn lại là giải nén, nên đổi hướng từ "kéo nhanh hơn" sang "giữ layer lại trên node": job chạy thành pod riêng để dùng cache image của node; quota giả qua device plugin để scheduler và autoscaler cùng hiểu ràng buộc "cùng node". Kéo image còn khoảng 12 giây, pipeline nhanh hơn 30–40%. Mercari 2026
- 2026 · Stripe: monorepo Ruby 50 triệu dòng, khoảng 50.000 build/tuần. Phân tích tĩnh không đúng với Ruby, nên ghi lại file mà mỗi test đã mở (thư viện
LD_PRELOADchặnopen), đảo thành index file → test (roaring bitmap), so hash file với build nền để chọn test. Trung bình chạy khoảng 5% bộ test (trung vị 0,5%), dưới 10% compute; luôn chạy test duyệt thư mục và test đang hỏng; build nền tìm bằng một query theo ID tăng dần theo tổ tiên commit. Stripe 2026 - 2026 · Yelp: Webpack → Rspack bằng cấu hình adapter (chép cấu hình gốc, chỉ thay phần không tương thích), bật dần theo trang trên CI; persistent cache của Webpack chứa đường dẫn tuyệt đối nên không dùng được trên CI, cache của Rspack thì được (cache ấm −80%). Build tích hợp nhanh hơn khoảng 52%. Yelp 2026
- 2026 · Rust: Miri ghi toàn bộ biến môi trường vào
target/; cachetarget/trong GitHub Actions (main ghi, PR đọc) làm secret lọt sang PR. Job ghi vào cache công khai không được thấy secret. Rust 2026 - 2026 · Stripe: golden dataset (đầu vào + đầu ra kỳ vọng, gồm ca sự cố cũ, không chứa PII) chạy trên mỗi PR như bản nhỏ của replay traffic lịch sử bằng Spark. Stripe 2026
- 2026 · Uber: Bazel không hỗ trợ sẵn JUnit 5 nên viết test runner riêng nối rule test của Bazel với JUnit Platform (tìm test, listener, lọc flaky) làm nền cho migration; CI kiểm thêm integration test, linter, coverage cho mỗi diff tự động. Uber 2026
- 2026 · Uber: kho artifact tự host hai DC (đĩa gắn liền, đầy đĩa phải rebalance tay, nhân bản lỗi âm thầm, nâng cấp có thể mất cả cụm) chuyển sang SaaS trên blob store cloud; build tải hơn 5 PB artifact mỗi tháng. Uber 2026
- 2026 · Optiver: CI có phần phải chạy trên bare metal (FPGA, kernel, benchmark CPU) nên không autoscale được; code tăng vì researcher, trader và AI cùng viết. Dựng observability từ webhook GitHub Actions để lập kế hoạch capacity, và dùng metadata build như A/B test cho nâng cấp compiler/OS. Optiver 2026
Các lựa chọn và đánh đổi
| Lựa chọn | Được | Mất | Nguồn |
|---|---|---|---|
| Chạy mọi test trước merge | Đơn giản, không bỏ sót | Không scale theo số service/target; flaky tăng | Airbnb 2020 |
| Chọn việc theo đồ thị phụ thuộc tĩnh (hash cây target) | Chính xác khi build tất định, khai báo rõ | Cần build system kiểu Bazel; tính đồ thị cũng tốn (CTC khoảng 5 phút) | Uber 2022, Riot Games 2021 |
| Chọn test theo phụ thuộc đo lúc chạy (file đã mở) | Đúng với ngôn ngữ động và phụ thuộc không phải code | Bỏ sót test không mở file (glob), phải liệt kê ngoại lệ; cần build nền gần đây | Stripe 2026 |
| Chặn thay đổi lớn theo giờ | Làm trong vài ngày, hiệu quả ngay | Người phải chờ hoặc dậy sớm; thay đổi rủi ro land lúc ít người trực | Uber 2022 |
| Môi trường sạch mỗi shard/job | Không nhiễm chéo | Chi phí dựng môi trường lấn át thay đổi nhỏ (trung vị tệ đi) | Uber 2022, Mercari 2026 |
| Trạng thái sống lâu (container, cache host, layer trên node) | Nhanh cho trường hợp phổ biến | Phải định danh đúng khi nào làm mới; node ấm tốn tiền | Uber 2022, Mercari 2026 |
| Remote cache artifact + kết quả test | Không build/test lại giữa máy, giữa review và land | Đòi build tất định; thêm một dịch vụ phải vận hành | Uber 2022 |
| Agent co giãn theo job | Không trả tiền agent ngồi không | Cần cấp credential và cấu hình lúc khởi động; cold start | Disney Hotstar 2020 |
| Đẩy test sâu sang CD (staging, canary) | Merge nhanh, CI ổn định hơn | Lỗi tích hợp lộ ra muộn hơn | Airbnb 2020 |
| Hàng đợi merge tuần tự (từng PR một) | Master luôn xanh, đảm bảo mạnh nhất | Thời gian chờ = độ dài hàng × một lượt CI; PR chờ nhiều ngày | Rust 2020 |
| Hàng đợi gom nhóm động, tự loại PR xung đột | Throughput cao, một PR xấu không kéo cả nhóm | Ưu tiên toàn hệ hơn công bằng từng PR; cần CI cho từng nhóm | GitHub 2024 |
| Hàng đợi suy đoán (cây build, cho thay đổi nhỏ vượt khi giao hoán) | Main luôn xanh, chờ ngắn ở monorepo lớn | Build suy đoán tốn tài nguyên; cần mô hình dự đoán thành công và thời gian build | Uber 2025 |
| Chọn test theo xác suất học từ lịch sử | Chạy ít test hơn phụ thuộc bắc cầu nhiều lần | Có tỉ lệ lọt (đặt ngưỡng); dữ liệu flaky làm hỏng mô hình | Meta 2018 |
| Cấu hình CI sinh trước và commit vào repo | Dễ đọc, không cần job sinh | Lớn tuyến tính theo số thành phần, chạm giới hạn của công cụ | Grab 2022 |
| Cấu hình CI sinh lúc chạy từ diff + quy ước thư mục | Kích thước cố định, chỉ chạy phần bị đổi | Phải giữ quy ước đường dẫn; pipeline sau merge phải dùng lại đúng diff của nhánh | Grab 2022 |
| File BUILD/repo là hợp đồng giữa CI và developer | Developer không phải học CI; pipeline review được như code | Cần build system chung (Bazel) hoặc quy ước rõ | Pinterest 2021, Yahoo 2017 |
| Build dạng đồ thị có đầu vào khai báo (BuildKit LLB) | Cache và song song theo từng bước | Phải viết bộ sinh plan; khác mô hình Dockerfile quen thuộc | Railway 2025 |
| Cổng ratchet (baseline + cấm thêm) | Siết chuẩn dần mà không cần đợt dọn lớn | Ma sát khi đổi tên/di chuyển file; cần người duyệt khi tăng hạn mức | Notion 2025 |
Quy tắc rút ra
- Thời gian của một thay đổi = dựng môi trường + build/test + chờ trong hàng đợi merge. Đo cả ba trước khi tối ưu cái nào; ở Uber và Mercari phần dựng môi trường chiếm phần lớn với thay đổi nhỏ. Uber 2022 Mercari 2026
- Tối ưu cho trung vị chứ không chỉ cho đuôi: hầu hết thay đổi là nhỏ, nên chi phí cố định mỗi lần chạy quyết định trải nghiệm. Uber 2022
- Chọn tín hiệu phụ thuộc hợp với ngôn ngữ: đồ thị build tường minh khi build tất định (Bazel), đo lúc chạy khi ngôn ngữ động (Ruby). Tín hiệu nào cũng có chỗ mù; liệt kê chỗ mù và luôn chạy phần đó. Stripe 2026 Riot Games 2021
- Chia việc theo cấu trúc phụ thuộc (root target) để một cây phụ thuộc nằm trên một máy; chia đều theo số lượng làm build lặp. Uber 2022
- Kết quả test là artifact cache được nếu khoá là hash của mọi đầu vào; dùng lại giữa lúc review và lúc merge. Uber 2022
- Dữ liệu dùng cho lựa chọn phải tìm được bằng một thao tác và tái lập được (cùng build nền → cùng tập test), để gỡ lỗi khi chọn sai. Stripe 2026
- Hệ CI là một dịch vụ có SLO: nó phụ thuộc nhiều dịch vụ khác, cấu hình sai chặn mọi người, nên cần kiểm cấu hình trước, metric riêng và đường rollback. Riot Games 2021 Disney Hotstar 2020 Mercari 2026
- Vá tạm bằng chính sách (chặn theo giờ) được, nhưng ghi rõ cái giá để nó không thành vĩnh viễn. Uber 2022
- Khoá cache chỉ được chứa những đầu vào thật sự ảnh hưởng tới kết quả. Một giá trị đổi mỗi lần (deployment ID, timestamp) đặt sớm làm mất cache của mọi bước sau; băm đúng phần mỗi bước dùng. Railway 2025 Uber 2022
- Cấu hình CI không nên lớn theo số thành phần: sinh từ diff và quy ước (Grab), hoặc từ đồ thị phụ thuộc mà developer đã khai báo (Pinterest). Grab 2022 Pinterest 2021
- Với hàng đợi merge tuần tự, rút ngắn một lượt chạy là đòn bẩy trực tiếp nhất; muốn hơn nữa thì phải gom thay đổi không xung đột (SubmitQueue) hoặc bỏ bớt đảm bảo. Rust 2020 Uber 2022
- Hệ CI khởi đầu từ một công cụ có sẵn (Jenkins, TeamCity) thường thành lớp điều phối riêng khi lớn: dữ liệu build, phiên bản, production được nối vào một chỗ, engine bên dưới thay được. Yahoo 2017 Wix 2020
- Đo lead time tới production, không chỉ thời gian CI (theo tác giả bài Stack Overflow 2021); CI nhanh mà deploy gom theo tuần vẫn giữ diff lớn. Stack Overflow 2021
- Remote cache bật lên chưa có nghĩa là trúng: đo tỉ lệ trúng và so input giữa CI và máy developer; mọi khác biệt môi trường lọt vào input (cờ CI, đường dẫn tuyệt đối, thư mục rỗng, thứ tự) làm cache vô dụng. SoundCloud 2019 SoundCloud 2019 Yelp 2026
- Cache theo task khuếch đại module hoá chứ không thay được nó: repo một khối lớn gần như không lợi; và chi phí khởi động của chính server cache phải nhỏ hơn task ngắn nhất. Mercari 2026
- Ép quy tắc quan trọng cho build bằng build fail có hướng dẫn sửa, không bằng tài liệu. SoundCloud 2019
- Chia shard theo thời gian chạy đo được, chừa capacity cho test nhanh; chọn test theo coverage cần lượt chạy đầy đủ định kỳ (Badoo: mỗi build phát hành) vì coverage luôn lệch một nhịp, và mất tác dụng với test phủ quá rộng (API test). Bumble 2019
- Thứ tự dựng quyết định cái gì cache được: đặt phần hay đổi ở cuối chuỗi phụ thuộc và đặt ràng buộc tương thích lên phía ít đổi; Rust 2025 dời std ra sau compiler để rebase không còn dựng lại tất cả. Rust (Rust Foundation) 2025
- Kiểm tra đắt thì chạy theo phạm vi thay đổi trên mỗi PR (mutation testing trên class đã đổi), bản đầy đủ theo yêu cầu, và đưa kết quả vào cổng có sẵn thay vì dựng cổng mới. Trendyol 2021 Cùng hướng với chọn test theo coverage ở Bumble 2019.
Câu hỏi mở
- Chọn test theo phụ thuộc bỏ sót bao nhiêu lỗi trên thực tế? Stripe nói "không giảm an toàn" nhưng không nêu tỉ lệ lỗi lọt qua; Uber dựa vào giả định build tất định. Meta 2018 là nguồn có ngưỡng: bắt ít nhất một test fail cho hơn 99,9% thay đổi lỗi, chạy khoảng một phần ba số test phụ thuộc (Meta 2018), nhưng đó là chọn theo xác suất, không theo phụ thuộc thuần. Badoo 2019 chọn theo coverage cho nhánh và patch nhưng vẫn chạy hết cho build phát hành, cũng không nêu tỉ lệ lọt (Bumble 2019).
- Monorepo và polyrepo: các nguồn ở đây phần lớn là monorepo; Pinterest 2021 đi giữa (một monorepo cho mỗi ngôn ngữ, để giới hạn số pipeline) nhưng không so sánh chi phí. Vẫn chưa có nguồn so sánh trực tiếp (xem câu hỏi tương tự ở Quản lý fleet và migrate code hàng loạt).
- Hàng đợi merge tuần tự (Rust 2020) và hàng đợi gom thay đổi: GitHub 2024 đo được thời gian chờ −33% khi đổi train sang merge queue (GitHub 2024), Uber 2025 đo P95 chờ −31% tới −45% khi đổi chiến lược ưu tiên của SubmitQueue (Uber 2025); đều là trước-sau trong cùng công ty, chưa có nguồn so hai kiểu hàng đợi trên cùng một workload.
- Tốc độ commit tăng nhờ AI (Stripe 2026 nhắc tới) sẽ đẩy hàng đợi merge kiểu SubmitQueue tới đâu; Uber 2025 nêu đúng rủi ro này (thay đổi xung đột tới trước khi xử lý xong cái trước) nhưng chưa có số liệu.
- Liên hệ: Deploy và release an toàn (sau merge), Cache và invalidation (remote cache, khoá theo nội dung), Nền tảng nội bộ cho service (đường ray chung) (CI là nền tảng nội bộ), Quản lý fleet và migrate code hàng loạt (thay đổi do máy tạo cũng phải qua CI), Batching và khấu hao round-trip (chi phí cố định mỗi lần chạy), Deploy và release an toàn (lead time tới production, Stack Overflow 2021).
Được nhắc tới trong
- Bảo mật hạ tầng và quản lý secret
- Coding agent trong engineering (migrate, viết lại, chạy song song, quyền hạn)
- Deploy và release an toàn
- Kiểm thử độ tin cậy (chaos, fault injection, mô phỏng tất định)
- Kiến trúc frontend
- Nền tảng nội bộ cho service (đường ray chung)
- Quản lý fleet và migrate code hàng loạt
- Jane Street 2014
- Riot Games 2016
- Stack Overflow 2016
- Zillow 2017
- Yahoo 2017
- Zillow 2017
- LinkedIn 2018
- Meta 2018
- Bumble 2019
- Appian 2019
- SoundCloud 2019
- SoundCloud 2019
- Slalom Build 2019
- Trendyol 2020
- Atlassian 2020
- Airbnb 2020
- Disney Hotstar 2020
- LinkedIn 2020
- Wix 2020
- Rust 2020
- Stack Overflow 2021
- Pinterest 2021
- Hudson River Trading 2021
- Grammarly 2021
- Trendyol 2021
- Riot Games 2021
- Uber 2022
- Grab 2022
- Hudson River Trading 2023
- Jane Street 2023
- +23 nữa