Artikel mendalam tentang teknologi yang membentuk masa depan.

Git Monorepo Patah: Pelajaran dari 30.000 Merge Sehari

Skala monorepo Git gagal dengan pola yang bisa diprediksi pada laju merge ekstrem. Pelajaran dari klien yang selalu online dan commit di sisi server.

Ilustrasi kurir robot yang berdesakan di meja kasir di tengah arsip raksasa berisi kotak-kotak file.
Git mengasumsikan setiap klien membawa seluruh arsip. Asumsi itu masih oke, sampai ribuan klien antre setiap detik.

Jika kamu menjalankan monorepo git, ada suatu titik di masa depanmu di mana semuanya mulai lepas kendali. Untuk Anthropic, angkanya sekitar 30.000 merge per hari, riwayat branch utama 100 GB, dan kira-kira 25 juta checkout CI setiap harinya. Kalau diambil secara naif, totalnya lebih dari 600 petabyte lalu lintas git. Setiap hari. Jawaban mereka adalah menulis sistem version control sendiri dalam lima bulan. Jawabanmu jangan itu. Tapi kesalahan yang mereka alami di jalan itu sama dengan yang saya lihat di tim-tim dengan skala sepersepuluhnya, jadi mari kita bahas satu per satu.

Kesalahan pertama: memperlakukan alur kerja terpusat seperti terdistribusi

Taruhan desain inti git adalah desentralisasi. Setiap clone adalah repositori lengkap: seluruh riwayat, seluruh object store, dan tetap berfungsi offline. Taruhan itu membuat git merajai dunia, dan untuk kebanyakan repo, itu masih tepat. Tapi ada satu hal yang hampir tak ada yang mau mengakui: hampir tak ada yang benar-benar memakai git dengan cara itu. Organisasimu punya satu remote otoritatif di GitHub atau GitLab. Developer terus-menerus push dan pull. Runner CI secara definisi selalu online. Kamu menjalankan sistem terpusat yang berpakaian terdistribusi, dan tetap membayar biaya terdistribusi: setiap job CI menarik riwayat yang tidak akan pernah dibaca, setiap sandbox agen mewujudkan packfile yang tidak mereka butuhkan.

Ini pelajaran pertama yang nyata dari redesain Anthropic. Ketika mereka mundur selangkah, mereka sadar bahwa klien mereka adalah “agen dan job yang secara definisi selalu online”, jadi mereka mendesain di sekitar server yang selalu bisa dijangkau. Klien sengaja dibuat bodoh: cache lokal yang terbatas, working copy di disk, dan filesystem watcher. Server yang menjawab blame, menghitung diff, dan melakukan merge. Ini kesimpulan yang sama dengan yang dicapai Google lewat Piper dan Meta lewat Sapling, dan ini bukan posisi anti-git. Ini pengakuan bahwa arsitektur harus mengikuti beban kerja yang sebenarnya, bukan beban kerja yang menjadi tujuan alat itu dirancang dua dekade lalu. Saya juga melihat pola ini di tooling keamanan: tim men-deploy arsitektur agen yang mendukung offline, lalu menjalankannya di lingkungan yang offline-nya tidak pernah terjadi, lalu heran kenapa lapisan sinkronisasinya jadi mimpi buruk.

Kesimpulan untuk timmu bukan “bangun VCS sendiri”. Tapi: audit asumsimu. Tuliskan properti git mana yang benar-benar kamu andalkan. Kerja offline? Fork sungguhan? Penandatanganan commit secara kriptografi? Kalau jawaban jujurnya adalah “satu remote, selalu online, CI mengerjakan semuanya”, berhentilah mengoptimalkan alur kerja terdistribusi yang tidak kamu miliki, dan mulailah mengoptimalkan biaya checkout dan query.

Kesalahan kedua: menutupi skala dengan mirror dan seed

Setiap tim repo besar melewati tahapan duka yang sama. Pertama shallow clone. Lalu sparse checkout dan promisor remote. Lalu mirror git internal, lalu “seed” snapshot di blob storage supaya job CI bisa bootstrap dari sesuatu yang dekat dengan tip-of-main. Anthropic menjalankan semua ini, dan di puncaknya ada beberapa ratus mirror internal. Mode kegagalannya selalu sama: workaround-nya tidak gagal dengan keras, tapi membusuk. Seed makin menjauh dari tip di antara setiap refresh. Partial clone merusak git blame dan git log --follow dengan cara yang membingungkan. Seseorang menjalankan bisect dan diam-diam mendapat hasil yang salah karena riwayatnya terpotong. Tidak ada yang sadar sampai incident review.

Yang terakhir ini yang bikin saya susah tidur. Bug kebenaran riwayat parsial adalah jenis kesalahan halus yang hidup di celah antara apa yang kamu kira dijamin sistem dan apa yang sebenarnya dilakukannya. Shallow clone tidak error saat kamu minta blame melewati kedalamannya; ia cuma memberi jawaban parsial. Kalau pipeline revert otomatismu mempercayai jawaban itu, kamu sudah membangun mesin yang dengan percaya diri me-revert perubahan yang salah.

  • Shallow clone merusak tooling yang bergantung pada riwayat (blame, bisect, merge-base) dengan cara yang gagal diam-diam, bukan dengan keras.
  • Seed snapshot menjauh dari tip-of-main; semakin tinggi laju merge-mu, semakin cepat penjauhannya, jadi workaround-nya justru memburuk tepat saat beban naik.
  • Armada mirror memperbanyak permukaan operasional: ratusan salinan stateful yang bisa tertinggal, rusak, atau kehabisan disk secara independen.
  • Setiap workaround yang menyentuh semantik riwayat butuh regression test, atau ia akan menggigitmu saat insiden.

Di skala Anthropic, perbaikannya bersifat struktural: tidak ada salinan repo yang sepenuhnya terwujud di mana pun, bahkan di server, dan semuanya content-addressed serta bisa di-cache secara horizontal. Di skalamu, perbaikannya lebih sederhana: ukur berapa banyak mesin yang menyimpan salinan penuh atau hampir penuh dari repo-mu, lalu jujur soal penjauhan dan mode kegagalan masing-masing.

Kesalahan ketiga: membiarkan setiap job CI memelihara salinannya sendiri dari repo

Ada pertanyaan yang layak kamu ajukan tentang armada CI-mu: berapa banyak job di antaranya yang butuh working copy sama sekali? Jawaban Anthropic, setelah membangun sistemnya, adalah “jauh lebih sedikit dari yang kami kira”. Job yang butuh diff antara commit dan merge base-nya, atau blame untuk sebuah file, atau daftar commit yang menyentuh suatu path, bisa langsung bertanya ke server lewat API. Tanpa clone, tanpa fetch, tanpa disk. Pipeline bisect dan revert otomatis mereka “tidak akan praktis dalam skala besar” tanpa akses programatik yang murah itu. Dan saya percaya, karena saya sudah melihat tim mencoba menjalankan pipeline serupa di atas clone lokal dan tenggelam dalam waktu fetch.

Prinsip ini berlaku jauh melampaui source control. Perlakukan checkout sebagai pengecualian yang mahal, bukan default. Saat sebuah job memang butuh file, sparse dan virtualized checkout, yang hanya mewujudkan direktori yang diminta atau bahkan hanya file yang benar-benar dibaca, bisa memangkas biaya hingga beberapa orde besaran. Protokol fetch Anthropic menghapus negosiasi git sepenuhnya: klien meminta tree dan blob immutable spesifik yang dibutuhkan, cache mana pun bisa menjawab, dan semuanya berperilaku seperti CDN berlapis, bukan server pintar yang menghitung packfile per klien. Kalau kamu pernah memprofiling server git yang meleleh di bawah beban CI, kamu tahu kenapa ini penting. Pembuatan packfile sangat berat secara CPU karena protokolnya meminta server menghitung delta terhadap apa yang sudah dimiliki tiap klien.

Kalau klienmu selalu online dan ada satu salinan otoritatif, setiap clone lokal yang kamu pelihara adalah cache yang kamu bayar penuh harganya, dan toh kamu tetap mendapatkan semantik cache darinya.

Kesalahan keempat: membiarkan biaya commit tumbuh mengikuti ukuran repo

Keputusan rekayasa paling menarik dalam desain mereka adalah changeset. Commit git menunjuk ke tree yang merepresentasikan seluruh state repo. Changeset mereka hanya mencatat daftar file yang berubah relatif terhadap parent pertamanya, plus pointer ter-content-address ke blob storage, yang ditambahkan ke write-ahead log. Tidak ada packfile yang perlu diterima, tidak ada locking, tidak ada koordinasi antar-server. Ref, yaitu branch dan tag, sengaja dikurangi perannya karena “state global yang harus disepakati setiap server adalah masalah skala yang mengancam”. Memindahkan ref adalah compare-and-swap pada satu baris Spanner, terpisah dari pembuatan commit.

Ilustrasi bergaya berisi paket di atas conveyor yang mengalir ke log bercahaya dan struktur data turunan.
Catat hanya yang berubah dalam write-ahead log; turunkan semua yang lain (blame, riwayat path, indeks graf) secara lazy dari log tersebut.

Gagasan pendampingnya adalah “derived data”: indeks blame, riwayat path, skip list commit-graph, semuanya dihitung secara rekursif dari parent setiap changeset, melalui satu mekanisme generik. Hitung secara eager atau lazy per tipe. Tambahkan jenis indeks baru tanpa menyentuh klien. Ini pola yang benar-benar bagus untuk sistem event-sourced mana pun. Saya pernah merekomendasikan bentuk yang sama untuk pipeline audit-log, di mana log append-only adalah kebenarannya dan setiap struktur query adalah proyeksi yang bisa dibangun ulang. Begitu ada orang yang memelihara proyeksi secara manual di luar mekanisme itu, di situlah drift mulai muncul.

Satu catatan dari sudut pandang keamanan: para komentator yang khawatir soal sentralisasi punya poin yang layak diambil serius. Sebuah sistem server-side tunggal tempat commit, merge, dan query riwayat berada adalah target bernilai tinggi, dan agen AI dengan akses tulis ke “satu repo untuk memerintah semuanya” memusatkan risiko dengan buruk. Anthropic membangun “sistem IAM source control” yang kaya fitur berdampingan dengan itu, dan detailnya lebih penting daripada struktur datanya. Kalau kamu memusatkan, perhitungan blast radius-mu ikut berubah. Anggarkan isolasi, kredensial per-agen, dan audit sejak hari pertama, bukan di kuartal ketiga. Tim yang menjalankan agen stateful di atas infrastruktur bersama sudah paham betul rasa sakit ini.

Kesalahan kelima: menganggap 30.000 merge sehari berarti 30.000 keputusan yang baik setiap hari

Rekayasanya memang mengesankan. Pertanyaan terbukanya adalah apa yang mengalir melewatinya. Seorang praktisi merangkumnya dengan blak-blakan: setiap kali mereka berhenti mereview kode yang dihasilkan AI, “saya nanti menemukan kode berantakan. Tidak setiap review menemukan kode berantakan, tapi cukup sering sehingga saya tidak bisa berhenti mereview semuanya.” Kalikan tingkat temuan itu dengan 30.000 merge sehari, dan kamu akan paham kenapa Anthropic juga harus membangun “cara-cara baru untuk mengelola dan mendaratkan kode yang sudah direview dalam jumlah besar”: permukaan review, antrean landing, pipeline revert otomatis. VCS bukan produknya. Landing pipeline-lah produknya. Source control baru menjadi bottleneck setelah kapasitas review menjadi bottleneck lebih dulu.

Ada juga detail jujur yang terselip di kisah-kisah mereka: para engineer di proyek itu menggambarkan sebagian besar peran mereka sebagai mengatakan “tidak” kepada coding agent. Prototipe pipeline ingestion yang mereka tulis tangan sebenarnya baik-baik saja, sampai model yang lebih baru menulis ulangnya dengan memori 20x lebih ringan dan 4x lebih cepat. Tapi untuk sampai ke sana dibutuhkan manusia dengan selera yang menentukan apa yang diterima. Ini sejalan dengan semua yang saya lihat: AI menggeser pekerjaan engineer dari menulis ke mereview, dan throughput review sekarang menjadi sumber daya yang langka. Kami pernah menulis tentang bagaimana setiap lapisan review membuat tim makin lambat. Bagian sulitnya, dengan kode hasil agen, menghapus lapisan review juga tidak aman. Yang kamu butuhkan adalah tooling review yang lebih baik, bukan review yang lebih sedikit.

Apa yang sebaiknya benar-benar kamu lakukan

Kamu bukan Anthropic. Kamu tidak punya anggaran token mereka, dan mereka sendiri mengakuinya. Kamu juga tidak punya 25 juta checkout harian. Tapi tool coding AI mendorong laju merge semua orang naik, dan titik tekanannya muncul dalam urutan yang bisa diprediksi. Inilah urutan langkah yang akan saya ikuti, dalam “Hukum Priya” tentang penyesalan paling kecil:

  1. Ukur dulu. Hitung checkout harian, byte yang di-fetch per job CI, dan berapa mesin yang menyimpan salinan penuh repo. Kemungkinan besar kamu punya masalah pemborosan sebelum masalah skala.
  2. Hilangkan checkout yang tidak perlu. Pindahkan pertanyaan metadata (diff, blame, silsilah) ke API, yaitu API GitHub/GitLab atau layanan internal yang tipis, sebelum kamu membeli infrastruktur apa pun.
  3. Buat sparse dan partial clone aman. Uji tooling bisect, blame, dan revert-mu terhadap shallow clone secara eksplisit, atau larang penggunaannya dalam otomatisasi.
  4. Jadikan CI berbasis fetch server-side dan objek immutable bila memungkinkan, dan perlakukan armada mirror sebagai utang teknis dengan bunga yang terus berbunga.
  5. Investasikan di landing pipeline, bukan format repo. Kapasitas review, merge queue, dan revert otomatis adalah tempat pengembangan skala agen pertama kali benar-benar patah.
  6. Baru kemudian pertimbangkan arsitektur VCS alternatif. Sapling itu open source dan memberimu sebagian besar manfaat client-server tanpa harus menulis sendiri.

Pelajaran terdalamnya sebenarnya bukan tentang git. Setiap tool mengandung asumsi tentang beban kerjanya, seperti manusia yang offline, satu commit dalam satu waktu, dan kode yang ditulis lebih lambat daripada direview. Asumsi-asumsi itu sekarang sedang dilanggar oleh agen, di infrastruktur, di review, dan di batas keamanan. Tim yang akan unggul bukanlah yang membangun ulang semuanya dari nol. Mereka adalah yang menyadari asumsi mana yang rusak lebih dulu, lalu memperbaiki tepat asumsi-asumsi itu.