Apakah Database Benar-Benar Diperlukan
(dbpro.app)- Semua database pada akhirnya adalah kumpulan file terstruktur di atas file system, sehingga aplikasi tahap awal dapat memperoleh performa yang memadai bahkan dengan mengelola file secara langsung
- Dengan mengimplementasikan server yang sama dalam Go, Bun, dan Rust lalu membandingkan tiga pendekatan pemindaian file, peta in-memory, dan pencarian biner di disk, terbukti bahwa akses file sederhana saja dapat mencapai throughput yang tinggi
- Metode peta in-memory menunjukkan performa terbaik (hingga 169k req/s), sementara SQLite stabil di 25k req/s tetapi memiliki overhead
- Sebagian besar layanan dapat menangani hingga sekitar 90 juta DAU hanya dengan satu file SQLite, sehingga pada tahap produk awal database terpisah belum diperlukan
- Database mulai diperlukan ketika dataset melebihi RAM atau ketika dibutuhkan join, pencarian multi-kondisi, penulisan serentak, dan transaksi
Apakah Database Benar-Benar Diperlukan
- Database pada akhirnya hanyalah kumpulan file; SQLite adalah satu file tunggal, sedangkan PostgreSQL terdiri dari direktori dan proses
- Semua database membaca dan menulis ke file system, bekerja dengan cara yang sama seperti memanggil
open()dari kode - Jadi inti persoalannya bukan “apakah akan menulis file”, melainkan “menggunakan file milik database atau mengelolanya sendiri”
- Banyak aplikasi tahap awal tetap bisa memperoleh performa yang cukup meski dikelola langsung
- Semua database membaca dan menulis ke file system, bekerja dengan cara yang sama seperti memanggil
Susunan eksperimen
- Server HTTP yang sama diimplementasikan dalam Go, Bun(TypeScript), dan Rust lalu dua strategi penyimpanan dibandingkan
- Menggunakan tiga file JSONL:
users.jsonl,products.jsonl,orders.jsonl - Membuat data lewat
POST /users, mengambil data lewatGET /users/:id - Hanya jalur baca (GET) yang dijadikan target benchmark
- Menggunakan tiga file JSONL:
-
Pendekatan 1: membaca file pada setiap request
- Saat request datang, file dibuka, semua baris dipindai, JSON diparsing, lalu diperiksa apakah ID cocok
- Rata-rata perlu membaca setengah isi file sehingga kompleksitasnya O(n)
- Semakin besar data, semakin tajam penurunan kecepatan pemrosesan request
-
Pendekatan 2: memuat seluruh data ke memori
- Saat startup, seluruh file dibaca dan disimpan ke hash map berbasis ID
- Penulisan dicerminkan sekaligus ke map dan file, sedangkan pembacaan cukup dengan satu lookup map sehingga O(1)
- File berperan sebagai penyimpanan persisten, map berperan sebagai indeks
- Mendukung pembacaan paralel dengan
sync.RWMutexdi Go danRwLockdi Rust
-
Pendekatan 3: pencarian biner di disk
- Solusi tengah untuk lookup cepat tanpa harus memuat semua data ke RAM
- Membuat file data yang diurutkan berdasarkan ID serta file indeks lebar tetap (58 byte/record)
- Menelusuri indeks secara O(log n) dengan
ReadAt, lalu membaca satu record pada offset terkait - Saat record baru ditambahkan, urutan akan rusak sehingga perlu regenerasi indeks atau merge berkala
- Pola merge ini mirip dengan cara kerja LSM-tree
Lingkungan benchmark
- Skala dataset: 10k, 100k, 1M record
- Alat beban: wrk, menjalankan request GET acak selama 10 detik dengan 4 thread dan 50 koneksi simultan
- Diuji pada mesin yang sama (Apple M1 Mac mini, macOS 15) dengan Go 1.26, Bun 1.3, Rust 1.94
- Di Go juga dibandingkan tambahan pencarian biner (disk) dan SQLite(modernc.org/sqlite)
Hasil utama
- Performa linear scan menurun: pada 1M record, Go turun ke 23 req/s dan Bun ke 19 req/s
- Pencarian biner (disk): pada rentang 10k~1M record, turun hanya 15% dari 45k ke 38k req/s
- Berkat efek page cache OS, area indeks bagian atas selalu tetap berada di memori
- SQLite: mempertahankan performa yang konsisten di 25k req/s dengan latensi rata-rata 2ms
- Pencarian biner sekitar 1,7x lebih cepat daripada SQLite, menunjukkan adanya overhead SQLite untuk lookup PK sederhana
- Metode peta memori memberikan performa terbaik: 97k~169k req/s, dengan latensi di bawah 0,5ms
- Bun lebih cepat daripada Go: Bun 106k req/s, Go 97k req/s
- Bun dibangun di atas JavaScriptCore + Zig(uWebSockets) dan melewati libuv
- Rust sangat unggul pada linear scan: 3~6 kali lebih cepat daripada Go, diduga karena efisiensi JSON parsing dan I/O
-
Pilihan terbaik per use case
- Throughput absolut tertinggi: Rust peta in-memory (169k req/s)
- Terbaik saat data tidak dimuat ke RAM: Go pencarian biner (~40k req/s)
- Jika membutuhkan SQL: SQLite (25k req/s)
- Implementasi paling sederhana: Go linear scan (~20 baris kode)
Arti dari 25.000 req/s
- Trafik web umum diasumsikan memiliki rasio puncak:rata-rata = 2:1
- Rata-rata 12.500 req/s → puncak sekitar 25.000 req/s
- Diasumsikan pengguna aktif melakukan 10 kali lookup per jam, dengan tingkat koneksi simultan 10% saat puncak
- Rumus request puncak: DAU × 0.000278
- Hasil perhitungan DAU jenuh untuk tiap pendekatan
- Go linear scan: 2.8M
- Go pencarian biner: 144M
- SQLite: 90M
- Go peta in-memory: 349M
- Bun peta in-memory: 381M
- Rust peta in-memory: 608M
- Sebagian besar produk tidak pernah mencapai angka ini
- Contoh: 10.000 pelanggan SaaS → 3 req/s, aplikasi 100.000 DAU → 30 req/s
- Kesimpulannya, sebagian besar produk awal tidak memerlukan database
- Bahkan bila dibutuhkan, satu file SQLite saja bisa menangani hingga 90 juta DAU
Kapan database diperlukan
-
Saat dataset tidak muat di RAM
- Pada puluhan juta record, indeks saja bisa membutuhkan beberapa GB
- Diperlukan paging data, dan database menanganinya secara otomatis
-
Saat perlu query berdasarkan field selain ID
- Pencarian multi-kondisi memerlukan file scan atau map tambahan
- Jika harus memelihara banyak map, pada dasarnya Anda sedang membangun query engine sendiri
-
Saat diperlukan join
- Harus membaca dan menggabungkan beberapa file, dan SQL lebih efisien untuk itu
-
Saat ada penulisan serentak dari banyak proses
- Peta in-memory di setiap instance terpisah sehingga konsistensi hilang
- Dibutuhkan satu sumber kebenaran eksternal → peran database
-
Saat dibutuhkan penulisan atomik antar entitas
- Misalnya perlu menjamin pembuatan pesanan dan pengurangan stok berhasil atau gagal bersama-sama
- Itu memerlukan implementasi transaction log tersendiri, sedangkan DB menyelesaikannya dengan ACID
- Jika tidak memiliki batasan seperti ini, maka alat internal, side project, dan produk awal
- Dapat berjalan cukup baik dalam RAM satu server
- File JSONL juga mudah dimigrasikan ke database nantinya
Lampiran dan ketersediaan kode
- Menyertakan kode server Go, Bun, dan Rust
- Menyediakan data seed serta skrip menjalankan benchmark (
run_bench.sh) secara terpisah - File ZIP berisi
go-server/,bun-server/,rust-server/,seed.ts - Skrip akan melakukan seed data dalam tiga skala, menjalankan uji beban dengan wrk, lalu berhenti
Informasi terkait DB Pro
-
DB Pro** adalah klien database untuk Mac, Windows, dan Linux**
- Menyediakan fungsi query, eksplorasi, dan manajemen secara terpadu
- Mendukung platform web kolaboratif dan AI bawaan
- Pada versi terbaru, mendukung koneksi ke database SQLite milik Val Town
- Di v1.3.0, ditambahkan fitur pembuatan database, editor multi-query, dan koneksi PlanetScale Vitess
26 komentar
Omong kosong apa ini
dikira orang pakai db karena performa?
Iya juga. Saya penasaran apakah ada insight baru, jadi saya lihat artikel aslinya, tapi ini apaan...
Bukannya membuka dengan pembahasan dasar seperti memori mahal jadi pakai disk, atau demi stabilitas operasional produksi, atau soal atomisitas, mereka malah langsung duduk membandingkan kecepatan, jadi rasanya sampai bikin senyum kecut.
Sambil memuat artikel dengan nada, 'Kami jual DB, tapi DB tidak selalu diperlukan!', mereka juga bicara seperti ini tanpa canggung—entah memang mau marketing atau apa, hmm... Mau dilihat secara positif pun, kadang jadi terasa sinis.
Anggap saja setidaknya saya dapat benchmark.
Menurut saya ini tulisan yang sangat bagus. Terutama materi yang memuat 'angka' seperti itu memang langka. Di zaman ketika sulit menemukan developer yang setidaknya punya 'gambaran kasar' tentang overhead dari kode yang kita buat dan tech stack yang kita pakai, saya membacanya dengan senang hati.
Saya juga setuju. Saya rasa ini adalah materi yang memberi intuisi penting tentang mechanical sympathy maupun pengaturan tempo pengembangan. Seperti
Latency Numbers Every Programmer Should Know.Dan saya tidak merasa tulisan ini dibaca seolah satu arah tertentu pasti selalu lebih baik. Justru angka-angka yang ditunjukkan semua pendekatan yang disebut dalam tulisan itu terlihat sebagai "performa yang lebih dari cukup untuk sebagian besar bisnis", jadi saya membacanya sebagai ajakan untuk memilih pendekatan yang sesuai dengan situasi masalah.
Balasan-balasan permatanya juga bonus.
Kalau memang ada alasan untuk melakukannya seperti ini, mungkin layak dipertimbangkan, bukan? Misalnya kalau ada batasan performa yang sangat ketat.
Tapi dalam kebanyakan kasus, apakah benar ada alasan untuk sengaja memilih ini? Bukan berarti DB tidak punya kelebihan juga..
Ini cuma terasa seperti perubahan cara berpikir, tapi kalian semua sensitif sekali ya.
Benar juga. Saat jumlah pengguna masih belum banyak di tahap awal bisnis, ini bisa dianggap sebagai usulan bahwa alih-alih membeli DB atau membuatnya rumit, bisnis bisa berjalan sampai mapan hanya dengan file I/O dasar.
Saya juga setuju. Dalam layanan, DB kadang dinilai lebih penting daripada yang sebenarnya diperlukan, dan terkadang ada investasi desain yang berlebihan seolah-olah jika normalisasi rusak maka akan jadi masalah besar.
Bukan berarti jangan memakai DB, tetapi cukup bagus jika kita menyegarkan cara pandang tentang mengapa kita memakainya dan apa sebenarnya inti mendasar dari sebuah layanan.
Seperti biasa, yang penting adalah keseimbangan.
Begitu memilih SQLite untuk server produksi, sejak saat itu kita harus terus-menerus memikirkan kapan harus pindah. Dulu biaya DB itu sendiri (biaya pembelian server, IDC, biaya lisensi, dll.) mahal sehingga layak dipertimbangkan, namun sekarang katanya bisa dibangun hanya dengan sekali klik, jadi apakah benar masih perlu dipikirkan?
Bahkan sekarang pun DB itu mahal.
Ini tipikal coding di kepala.
Tentu saja, untuk "proyek tahap awal atau aplikasi berskala kecil", mungkin tidak perlu database. Bukan cuma database, elemen lain juga bisa asal pilih saja. Masalahnya muncul saat skalanya membesar. Ini cuma tulisan yang melihat angka-angka untuk seru-seruan saja.
https://hackers.pub/@gnh1201/2025/…
Terkadang tidak perlu memasang database terpisah. Meski hanya untuk Windows...
Saya ngakak begitu lihat judulnya.
Saya kadang berpikir apakah entitas-entitas utama memang harus menjamin persistensi melalui RDBMS. Toh sudah ada cukup banyak teknologi alternatif untuk menyediakan SSOT.
Kalau SQLite rusak, sudah tidak ada jalan keluar..
Apakah ada kasus di mana
sqlitebisa rusak? Saya penasaran. Tentu di luar perpindahan atau penghapusan file yang tidak normal.Komentar Hacker News
Saya sangat menyukai tulisan ini. Ini menunjukkan dengan sangat baik betapa cepatnya komputer
Namun saya tidak setuju dengan kesimpulan di bagian akhirnya. Penulis mengatakan ini tidak berlaku untuk banyak aplikasi yang punya batasan “perlu ditulis oleh beberapa proses secara bersamaan”, tetapi dalam praktiknya, bahkan produk tahap awal pun sering punya worker terpisah seperti cron atau message queue yang juga perlu menulis secara bersamaan
Kita bisa saja memaksa agar hanya server utama yang menulis, tetapi itu meningkatkan kompleksitas arsitektur
Jadi dari sudut pandang skala murni saya setuju dengan penulis, tetapi dalam gambaran yang lebih luas saya rasa lebih baik memakai database. Terutama SQLite adalah pilihan yang masuk akal
Kalau butuh skala, data yang sering diakses tinggal di-cache di memori. Kombinasi yang saya pakai adalah SQLite + cache in-memory
S3 kadang bisa dipakai, tetapi tetap ada banyak batasan untuk menjadikannya pengganti penuh
Jauh lebih sederhana dan murah karena tidak perlu mengelola server DB terpisah atau backup-nya
Saya benar-benar menyukai SQLite, tetapi saya sadar itu bukan jawaban untuk semua masalah
Saat membuat aplikasi kamus di sisi klien, saya mencoba port SQLite wasm, tetapi file DB-nya lebih besar dari perkiraan, kompresinya juga kurang bagus, dan loading-nya lambat
Akhirnya saya beralih ke pendekatan membuat indeks langsung dari file TSV asli, lalu dikompresi dengan zstd, dan didekompresi setiap kali di wasm. Ini ternyata jauh lebih cepat daripada SQLite
Ukuran modul juga turun dari 800KB menjadi 52KB, dan menjalankan beberapa instance sekaligus pun tidak memberatkan
Untuk pencarian string saya memakai stringzilla, dan itu luar biasa cepat
SQLite memang hebat, tetapi bukan jawaban untuk setiap situasi
Benchmark SQLite itu kurang dioptimalkan
Cukup tambahkan
hanya dengan ini saja performa di mesin saya naik dari 27,700 r/s menjadi 89,687 r/s
Saya juga mencoba prepared statement dan mengubah timestamp menjadi int, tetapi tidak ada perbedaan besar
Tulisannya lumayan, tetapi bagian “semua DB mengakses filesystem dengan open()” itu tidak akurat
Aplikasi seperti SQLite memakai mmap untuk memetakan file langsung ke ruang memori. Cara ini bisa melewati syscall dan mengaksesnya jauh lebih cepat
Di bagian akhir tulisan dijelaskan proses membaca seluruh file ke memori, dan rasanya akan lebih baik jika memakai mmap
Namun saya juga tidak yakin mmap selalu lebih baik. Ada orang yang lebih suka menanganinya langsung di logika aplikasi daripada bergantung pada API OS
Untuk paper terkait, lihat riset mmap dari CMU
Ungkapan “berfungsi seperti open()” memang agak disederhanakan, tetapi secara teknis tetap benar
Dulu sekali saya membuat aplikasi web penjualan kecil dengan Perl, dan karena tidak bisa memasang apa pun di server ISP, saya memakai hash berbasis file
Klien itu terus memakainya selama lebih dari 20 tahun sampai meninggal dunia, lalu keluarganya mengambil alih dan menggantinya dengan Wordpress
Saat terakhir saya cek, jumlah pesanannya sudah ratusan ribu, tetapi performanya masih baik-baik saja
Berkat kemajuan hardware, struktur yang terasa seperti hack ini bertahan jauh lebih lama dari perkiraan. Kalau sekarang, rasanya SQLite pun sudah lebih dari cukup
Kalau mencoba mengimplementasikan storage sendiri, kita jadi bisa memahami bagaimana DB bekerja
Kita harus menangani indeks dan struktur data secara efisien, dan pada akhirnya akan sampai pada kesimpulan “kalau ini bukan main-main, seharusnya sejak awal pakai DB”
Relational Databases Aren’t Dinosaurs, They’re Sharks
Dibanding manfaat kecil yang didapat pada aplikasi mungil, membuang waktu untuk menciptakan ulang roda jauh lebih merugikan
Pada zaman Kapur, hiu sudah hampir sama bentuknya dengan sekarang, dan tetap bertahan tanpa banyak perubahan sesudahnya
Sementara dinosaurus, pterosaurus, dan mosasaurus telah punah, hiu, buaya, dan ular besar masih ada hingga kini hampir tanpa perubahan berkat desain yang teroptimasi
Saya rasa DB relasional juga seperti itu
Menyenangkan membaca tulisan seperti ini
Meski begitu, saya tetap memakai DB dengan SQL dan transaksi dalam 99% kasus
Namun belakangan ini, untuk proyek pribadi, saya sempat mengelola data dengan filesystem sederhana berbasis file YAML, dan pada skala saya tidak ada masalah performa sama sekali
Bisa dibaca manusia dan bisa di-diff lebih penting bagi saya daripada performa
Tetapi dalam kebanyakan kasus, saya tetap akan memilih DB dengan bahasa query dan konsistensi yang terjamin
Pada akhirnya, kita selalu membutuhkan fitur DB dan jaminan ACID
Setiap kali harus memakai flatfile store legacy, saya selalu kesulitan karena harus memaksakan konsistensi, transaksi, dan bahasa query ke atasnya. Ujung-ujungnya tetap menciptakan ulang roda
Saat atomisitas dibutuhkan, DB itu wajib
Mengimplementasikan write atomik di atas filesystem itu sangat rapuh
Karena alasan seperti ini, banyak DB mengalami masalah kerusakan data saat crash. Dulu RocksDB di Windows pernah seperti itu
Mengimplementasikannya sendiri terasa seperti tindakan gila. Memang ada baiknya belajar cara menulis dengan aman lewat API OS, tetapi sekarang itu sudah jadi keahlian yang sangat niche
Selain itu, besar kemungkinan penerus kita tidak bisa memeliharanya. Pada akhirnya tetap akan pindah ke DB
Minimal harus menulis ke file sementara di filesystem yang sama, lalu fsync dan ganti dengan rename
Kalau seluruh DB ditulis ke file sementara, lalu di-flush dan diganti dengan move, itu bersifat atomik di Unix
Hanya saja ini sama sekali tidak scalable. Update kecil pun mengharuskan seluruh file ditulis ulang, dan tetap perlu manajemen lock. Ini cuma menyelesaikan sebagian dari ACID
Sebagai catatan, DB OLAP DuckDB juga bekerja sangat baik untuk workload out-of-core
Tautan dokumentasi resmi
Kita bisa saja hidup tanpa kulkas, tapi pasti ada ketidaknyamanan.
Kalau bisa pakai kulkas, tidak ada alasan untuk tidak memakainya.
Apakah Anda pendukung Ilbe, Nora?
Kalau bilang tidak, semua langsung dibilang Ilbe ya? Aku orang Gyeongsang-do juga, lho?
Saya ingin melaporkannya, tapi saya tidak tahu cara melaporkannya. Aduh.
Komentar ini tampaknya menunjukkan pola pikir sempit para pengembang Korea dan juga level GeekNews.
Tingkat yang dimaksud itu tingkat seperti apa, apa alasanmu menilai levelnya seperti itu, coba jelaskan dengan menggunakan setidaknya dua dari logika/fakta/sains/statistik ya ya
Haha, dari kata-katanya saja sudah kelihatan dia tipe pengguna dari DC, Ilbe, atau Femco, jadi tidak usah dipedulikan.