SQLite Terdistribusi: 5 Mitos Diuji Setelah 12 Tahun
Dua belas tahun SQLite terdistribusi (Raft, Litestream, Turso, D1): kami uji lima mitos soal konsistensi, replikasi, dan kapan pakai Postgres.

SQLite terdistribusi berubah dari proyek akhir pekan seseorang menjadi kategori produk yang didanai ventura, dan hampir tidak ada engineer yang menyadari dekade di antaranya. Pada September 2014, Philip O'Toole memasang log Raft di depan SQLite, mereplikasi setiap write ke seluruh cluster, lalu mengunggah kodenya ke GitHub sebagai rqlite. Dua belas tahun kemudian sudah ada ekosistem utuh — dqlite, Litestream, LiteFS, cr-sqlite, libSQL/Turso, Cloudflare D1 — dan sebagian besar yang orang yakini tentangnya keliru dengan cara yang menarik.
Saya pernah menjalankan database clustered di production dan membereskan kekacauan saat failure, jadi biar kamu tidak ikut pusing: perdebatan soal SQLite terdistribusi hampir tidak pernah benar-benar soal SQLite. Yang diperdebatkan adalah pertanyaan apa yang sebenarnya kamu ajukan — bagaimana kalau mesinnya mati, bagaimana kalau mesinnya mati dan saya tidak bisa menunggu, atau bagaimana kalau memang tidak ada mesin sama sekali. Berikut lima mitos, diuji terhadap dua belas tahun sejarahnya.
Mitos 1: SQLite terdistribusi itu ide baru
Gelombang tulisan tentang SQLite yang direplikasi dimulai sekitar 2021, ketika Litestream dan gerakan "SQLite is enough" makin ramai, dan Turso serta Cloudflare D1 datang dengan pendanaan dan postingan peluncuran. Jadi muncul anggapan bahwa ada orang pintar yang baru-baru ini sadar SQLite bisa direplikasi. Padahal sistem Raft-di-atas-SQLite pertama sudah dirilis pada 2014, dan itu bahkan bukan replikasi SQLite yang pertama — Expensify sudah melakukannya secara internal dengan protokol gaya Paxos selama bertahun-tahun sebelum merilis Bedrock pada 2016, dan ActorDB memberi setiap Erlang actor database SQLite sendiri yang direplikasi dengan Raft di era yang kurang lebih sama.
Kenapa ini penting selain soal kredit? Karena desain yang bertahan dua belas tahun reinvensi independen memberi sinyal. Setidaknya delapan tim berbeda, dengan kebutuhan dan protokol berbeda, melihat masalah ini dan sampai pada arsitektur yang sama: SQLite sebagai storage engine, replikasi dipasang dari luar. Tidak ada yang menemukan alasan untuk berhenti. Ketika kamu melihat pola seperti itu — implementasi ulang yang konvergen selama satu dekade — kamu sedang melihat ide yang benar-benar bagus, bukan siklus hype. Bandingkan dengan kategori yang muncul sebentar lalu hilang; yang ini terus berakumulasi.
Ini juga penting karena keputusan desain lama masih menjadi beban utama. rqlite memilih menjadi sistem CP pada 2014 — write lewat leader, mayoritas harus mengakui, dan minoritas yang terpartisi menolak write — dan tidak pernah mengubah pilihan itu. Satu pilihan tersebut menentukan HTTP API, level konsistensi baca, dan perilaku snapshot. Tim yang memperlakukan konsistensi sebagai toggle konfigurasi yang diputuskan belakangan biasanya menyesal; jurang antara spesifikasi yang kamu asumsikan dan yang benar-benar kamu implementasikan adalah tempat bug terdistribusi berkembang biak.
Mitos 2: Raft di atas SQLite memberimu Postgres terdistribusi yang murah
Ini mitos paling mahal dalam daftar. Premisnya terdengar menggoda: ambil database yang paling banyak dipakai di dunia, tambahkan konsensus, dan lewati beban operasional sistem client-server. Yang sebenarnya kamu dapat adalah database single-writer di mana setiap write membayar round trip jaringan ke mayoritas node, dan permukaan SQL SQLite — tanpa stored procedure, sistem tipe yang tipis, primitif konkurensi yang terbatas — tetap sama seperti SQLite.
Biaya write path adalah bagian yang jujur. Commit SQLite lokal cuma beberapa fsync. Commit yang direplikasi Raft: leader menambahkan ke log-nya, mengirim entry ke follower, menunggu mayoritas menyimpannya ke disk, menerapkannya ke SQLite, baru membalas. Di LAN yang sehat itu sekitar satu atau dua milidetik, bukan puluhan mikrodetik. Lintas region, yang membatasi adalah kecepatan cahaya ditambah disk. Untuk beban berat baca dengan laju write sedang — penyimpanan konfigurasi, metadata service discovery, control plane kecil — itu tidak masalah, dan itulah ceruk yang memang dibangun rqlite (asal-usulnya adalah sistem clustered yang butuh sedikit penyimpanan relasional, tanpa jawaban bagus soal node mana yang harus memegangnya). Untuk workload OLTP yang panas, ini alat yang salah.
Lalu ada realitas operasional yang tidak pernah ditulis di README: pemilihan leader adalah mode kegagalan yang sekarang jadi tanggung jawabmu. Split-brain memang dicegah lewat voting mayoritas, tapi itu berarti cluster tiga node yang kehilangan dua node akan menolak semua write. Kamu menukar "database mati karena server mati" dengan "database mati karena quorum mati", dan yang kedua lebih sulit dijelaskan ke on-call-mu jam 3 pagi. Kalau kamu belum memikirkan pengujian gaya Jepsen untuk sistem yang kamu pilih, sebaiknya mulai — seorang komentator Hacker News bertanya tajam apakah rqlite pernah diuji Jepsen, karena sistem yang belum biasanya menyimpan kejutan. Sementara itu, seorang engineer berpengalaman dalam diskusi yang sama mencatat bahwa dengan tooling modern, menjalankan Postgres sungguhan sudah cukup mudah sehingga "pakai saja database server" kembali menjadi default yang sah. Dia tidak salah.

Mitos 3: Replikasi berarti konsensus
Jika ada satu wawasan yang benar-benar diberikan oleh sejarah dua belas tahun ini, itu adalah: "SQLite yang direplikasi" bukan satu desain, melainkan tiga sudut dari ruang desain, dan kemunculannya berurutan dengan cara yang menarik. Mencampuradukkannya adalah cara tim berakhir menjalankan cluster Raft untuk menyelesaikan masalah backup.
- Konsensus (CP). rqlite, dqlite. Satu leader, konsistensi kuat, cluster sungguhan. Menjawab: "bagaimana kalau mesinnya mati dan saya tidak bisa menunggu restore?" Harganya: latensi write dan operasi quorum.
- Streaming (satu writer). Litestream, lalu LiteFS. Tanpa konsensus sama sekali — WAL SQLite di-stream ke object storage, memberi disaster recovery hampir kontinu untuk satu node. Menjawab: "bagaimana kalau mesinnya mati?" Harganya: jendela kecil kemungkinan kehilangan data dan waktu restore dalam hitungan detik sampai menit.
- Merge (AP). cr-sqlite dan gerakan local-first. CRDT sebagai ekstensi SQLite, banyak writer yang menyimpang lalu digabung tanpa leader. Menjawab: "bagaimana kalau tidak ada mesin pusat sama sekali?" Harganya: konsistensi eventual dan semantik merge yang harus kamu rancang sendiri.
Argumen Ben Johnson untuk Litestream layak dihormati karena benar untuk sebagian besar aplikasi: mereka berjalan di satu mesin dan butuh cara untuk pulih saat mesin itu mati, bukan cluster. Pertanyaan pertama — "bagaimana kalau mesinnya mati" — jauh lebih umum daripada yang kedua — "dan saya tidak bisa menunggu restore". Saya pernah melihat tim men-deploy cluster Raft tiga node untuk melindungi database yang kebutuhan RTO-nya adalah "kapan-kapan sebelum makan siang". Itu bukan rekayasa keandalan, itu cargo cult. Sebagai penutup yang manis, pendekatan streaming WAL Litestream akhirnya menginspirasi cara rqlite sendiri menangani WAL di v8 — cabang streaming memberi umpan balik ke cabang konsensus.
Jadi sebelum memilih alat, tulis pertanyaannya. Harfiah. "Saat node X mati, write harus kembali berjalan dalam N detik, dan kami menerima kehilangan M detik terakhir data yang sudah di-commit." Jika M beberapa detik dan N satu menit, Litestream-ke-S3 adalah jawabanmu dan itu tidak akan pernah membangunkanmu karena quorum. Jika M nol dan N hitungan detik, kamu berada di wilayah konsensus dan akan membayarnya di setiap write. Ini disiplin yang sama dengan threat model apa pun: beri nama kegagalannya sebelum membeli pertahanannya, seperti pendekatan sistem yang tahan terhadap bencana dengan memutuskan sejak awal bencana mana yang sedang kamu tahan.
Mitos 4: "SQLite di edge" yang dikelola menghilangkan trade-off
Uang di kategori ini mengalir ke platform — Turso mendapat pendanaan ventura dan kemudian diakuisisi Supabase; Cloudflare merilis D1 di dalam jaringan edge-nya. Janjinya: orang lain kini menangani bagian terdistribusi yang sulit. Kadang itu benar. Kadang itu cuma pemasaran, dan rahasia kotornya bocor: seorang developer Cloudflare pernah mengakui secara terbuka bahwa D1 pada dasarnya adalah pembungkus untuk satu Durable Object singleton yang mengekspos database SQLite-nya, dan kamu sering lebih baik memakai storage Durable Objects secara langsung. Itu bukan database terdistribusi dalam arti konsensus; itu satu file SQLite dengan platform di sekelilingnya. Pengguna D1 di production melaporkan keandalan yang sepadan.
Bukan berarti opsi terkelola itu buruk. Artinya trade-off-nya tidak hilang — ia pindah ke balik API yang tidak bisa kamu periksa. Saat menjalankan rqlite sendiri, kamu tahu persis apa arti CP: tiga node, satu leader, ack mayoritas, minoritas yang terpartisi menolak write. Saat membeli "SQLite di edge", kamu harus mengajukan pertanyaan yang sama pada kotak hitam: di mana writer-nya, apa yang terjadi saat partisi, berapa durability window yang sebenarnya? Jika jawaban vendor kabur, review insiden kamu juga tidak akan jelas.
Replikasi sebagai layanan tidak menghapus pertanyaan konsistensi. Ia hanya memindahkan jawabannya ke infrastruktur orang lain, tempat kamu tidak bisa mengauditnya.
Pola historisnya layak dipahami: sistem open-source (rqlite, dqlite, Litestream) sudah mengerjakan ide ini selama delapan tahun sebelum ada yang menjualnya, dan modal mengalir ke siapa pun yang mengubah ide itu menjadi layanan dengan tagihan. Itu nasib umum infrastruktur. Membeli sering kali pilihan yang tepat — tapi belilah dengan mata terbuka tentang sudut mana dari ketiga itu yang sebenarnya kamu dapatkan.

Mitos 5: Konsistensi kuat adalah peningkatan gratis dibanding backup
Orang sering membingkai pilihannya sebagai backup (lemah, murah) versus konsensus (kuat, mahal tapi jelas lebih baik). Tidak benar. Konsistensi kuat lewat Raft adalah produk yang berbeda, bukan versi lebih baik dari produk yang sama, dan ia membebankan pajak berkelanjutan yang tidak pernah dibebankan backup.
Pajak pertama: throughput. Seorang praktisi yang memakai keduanya mencatat bahwa rqlite memberimu jaminan "tersimpan di lebih dari satu tempat" tapi jauh lebih lambat daripada database satu node — itu round trip konsensus, dan tidak pernah hilang. Pajak kedua: semantik yang halus. Jika mereplikasi dengan mengirim statement SQL, kamu mewarisi masalah determinisme — fungsi seperti random() atau datetime('now') bisa berbeda antar node kecuali lapisannya menulis ulang, itulah sebabnya beberapa implementasi hanya mendukung subset SQL SQLite. Replikasi di level WAL menghindari itu, tapi kamu terikat pada format on-disk dan layout page SQLite. Tidak ada penempatan lapisan tanpa kompromi. Pajak ketiga: transaksi terdistribusi memang sulit. Seorang engineer menceritakan evolusi desain di mana setiap statement dalam transaksi adalah perintah Raft terpisah — kurang lebih benar tapi lambat — menjadi desain di mana node pemrakarsa menjalankan seluruh transaksi secara lokal, me-rollback-nya, lalu mengirim satu perintah commit dengan seluruh batch. Itu jenis pelajaran yang hanya didapat dengan benar-benar mengoperasikan sistem ini.
Berikut ilustrasi minimal perbedaan write path, menggunakan HTTP API rqlite:
# Local SQLite: one process, one fsync, microseconds.
sqlite3 app.db "INSERT INTO kv VALUES ('flag', 'on')"
# rqlite: this HTTP call hides a Raft round trip —
# leader log append, replication to a majority, then apply.
curl -XPOST 'localhost:4001/db/execute?pretty' \
-H 'Content-Type: application/json' \
-d '["INSERT INTO kv VALUES (?, ?)", "flag", "on"]'
# The guarantee changed: the write now survives the loss
# of any single node. So did the latency budget.
Dan perhatikan apa yang tidak kamu dapatkan: skala baca. Raft mereplikasi log supaya follower bisa mengambil alih; ia tidak membuat follower melayani baca yang konsisten kuat secara default (rqlite menyediakan level konsistensi baca justru karena ini trade-off). Jika kamu datang demi "terdistribusi" dengan harapan kapasitas baca yang lebih besar, yang kamu butuhkan adalah read replica, bukan konsensus.
Apa yang benar-benar diajarkan dua belas tahun Raft di atas SQLite
Sejarah kategori ini adalah bukti yang luar biasa bersih tentang bagaimana ide infrastruktur matang. Pertama, seseorang membangun hal yang prinsipil untuk kebutuhan konkret (rqlite, dari masalah clustering nyata di pekerjaan nyata). Lalu yang lain membangunnya ulang sesuai batasan packaging mereka — dqlite dari Canonical adalah library yang kamu embed karena Canonical butuh database di dalam produknya, sedangkan rqlite adalah server yang kamu jalankan di samping produk siapa pun. Kemudian ada yang berargumen bahwa kasus umum lebih kecil daripada yang diasumsikan solusi prinsipil (Litestream), terbukti benar, dan seluruh bidang itu melakukan kalibrasi ulang. Akhirnya platform membungkusnya dan menjualnya. Jika kamu cukup lama di infrastruktur, kamu akan melihat film ini lagi — agen LLM sedang mempelajari ulang pelajaran sistem terdistribusi dengan cara yang sama sekarang.
Rekomendasi tanpa basa-basi saya, setelah semua ini: mulai dengan SQLite satu node plus streaming WAL ke object storage. Mengagumkan seberapa jauh itu bisa membawamu, dan cerita kegagalanmu adalah restore, bukan postmortem konsensus. Naik ke sistem berbasis Raft hanya saat kamu bisa menyatakan dalam satu kalimat kebutuhan ketersediaan yang tidak bisa dipenuhi streaming — dan terima tagihan latensi write dan operasi quorum yang menyertainya. Pilih Postgres begitu kamu butuh permukaan SQL-nya atau throughput multi-writer. Dan jika tidak ada yang cocok, dunia database embeddable juga punya pilihan, dari database graph embeddable sampai sudut CRDT local-first.
Ringkasan membongkar mitos: SQLite terdistribusi tidak baru, bukan Postgres murah, bukan satu desain, tidak dibuat aman oleh pembungkus terkelola, dan bukan peningkatan gratis dibanding backup. Ini adalah desain dengan tiga sudut yang sudah berusia dua belas tahun, terpetakan dengan baik, masing-masing benar untuk pertanyaan yang berbeda. Engineer yang terbakar adalah mereka yang tidak pernah menuliskan pertanyaannya.


