Menyimpan data untuk proyek kecil seringkali terasa berlebihan jika harus menyiapkan PostgreSQL atau MySQL — konfigurasi server, koneksi, migrasi, semuanya harus ada sebelum bisa menulis satu baris data pertama. Di sisi lain, menyimpan langsung ke JSON mentah tidak aman dan tidak skalabel begitu data mulai tumbuh.
SawitDB hadir di antara dua ujung tersebut. Ini adalah database file-based untuk Node.js yang menyimpan data dalam format .sawit binary dengan arsitektur paged storage 4KB — cukup solid untuk production ringan, tapi cukup ringan untuk dijalankan tanpa setup tambahan. Satu hal yang membuatnya berbeda: SawitDB membawa Agricultural Query Language (AQL), sebuah sintaks query berbasis terminologi pertanian Indonesia — TANAM, PANEN, PUPUK, GUSUR — sebagai alternatif SQL konvensional. Keduanya didukung penuh.
Proyek ini dibangun oleh WowoEngine dan dilisensikan MIT. Zero dependency — hanya butuh Node.js standar.
Arsitektur dan Cara Kerja SawitDB
SawitDB menggunakan model hybrid: data ditulis ke file .sawit dalam halaman (page) berukuran 4KB, sementara data yang sering diakses disimpan di memory cache untuk akses yang lebih cepat. Setiap write dilindungi oleh Write-Ahead Logging (WAL) sehingga crash tidak akan merusak data yang sudah di-commit.
Indeks menggunakan struktur B-Tree, yang memberikan kompleksitas pencarian O(log n) bahkan saat tabel tumbuh besar. Dengan pendekatan ini, SELECT berdasarkan primary key bisa mencapai ~247.000 operasi per detik menurut benchmark internal proyek.
Untuk kebutuhan multi-client, SawitDB menyediakan mode server yang berjalan melalui protokol TCP sawitdb:// dengan dukungan authentication dan worker pool multi-threaded.
Instalasi
Install via npm atau bun — tidak ada dependency tambahan yang perlu disiapkan:
npm install @wowoengine/sawitdb
Untuk menjalankan SawitDB sebagai server:
node bin/sawit-server.js
Server akan berjalan di 0.0.0.0:7878 secara default. Untuk mengaksesnya lewat CLI interaktif:
node cli/remote.js
Operasi Database Dasar dengan AQL
SawitDB mendukung dua sintaks secara bersamaan — AQL dan SQL generik. Keduanya menghasilkan output yang identik. Di bagian ini kita pakai AQL supaya terasa karakternya.
Membuat dan Memilih Database
Buat database baru dengan perintah BUKA WILAYAH, lalu masuk ke dalamnya:
BUKA WILAYAH toko_buku
MASUK WILAYAH toko_buku
Padanan SQL-nya adalah CREATE DATABASE dan USE. Untuk menghapus database:
BAKAR WILAYAH toko_buku
Membuat Tabel
Buat tabel buku dengan kolom standar:
BUKA LAHAN buku (
id INTEGER PRIMARY KEY AUTOINCREMENT,
judul TEXT NOT NULL,
penulis TEXT,
harga INTEGER,
stok INTEGER DEFAULT 0
)
Ini setara dengan CREATE TABLE. Kolom id di-set sebagai primary key dengan auto increment.
Menyimpan dan Membaca Data
Simpan data dengan TANAM KE:
TANAM KE buku (judul, penulis, harga, stok)
BIBIT ('Laskar Pelangi', 'Andrea Hirata', 89000, 15)
TANAM KE buku (judul, penulis, harga, stok)
BIBIT ('Bumi Manusia', 'Pramoedya Ananta Toer', 95000, 8)
TANAM KE buku (judul, penulis, harga, stok)
BIBIT ('Ronggeng Dukuh Paruk', 'Ahmad Tohari', 75000, 20)
Baca data dengan PANEN ... DARI:
PANEN judul, penulis, harga DARI buku DIMANA stok > 10
Hasilnya akan mengembalikan dua buku dengan stok di atas 10. Untuk membatasi jumlah baris yang dikembalikan:
PANEN * DARI buku LIMIT 5
Update dan Delete
Ubah data dengan PUPUK ... DENGAN:
PUPUK buku DENGAN harga=92000, stok=12 DIMANA judul='Laskar Pelangi'
Hapus baris dengan GUSUR DARI:
GUSUR DARI buku DIMANA stok = 0
Selalu sertakan klausa DIMANA saat menggunakan PUPUK atau GUSUR. Tanpa kondisi, seluruh isi tabel akan terpengaruh.
Query Lanjutan
Indeks untuk Performa
Buat indeks pada kolom yang sering dijadikan kondisi pencarian:
INDEKS buku PADA penulis
Setelah indeks dibuat, query dengan kondisi pada kolom penulis akan menggunakan B-Tree lookup alih-alih full table scan.
Full-Text Search dengan BLUSUKAN
SawitDB menyediakan full-text search melalui perintah BLUSUKAN:
BLUSUKAN KE buku CARI "Pramoedya"
Ini akan mencari kata “Pramoedya” di seluruh kolom teks dalam tabel buku.
Agregasi dan GROUP BY
Hitung total stok per penulis:
PANEN penulis, SUM(stok) DARI buku
KELOMPOKKAN BERDASARKAN penulis
Filter hasil agregasi dengan HAVING:
PANEN penulis, COUNT(*) DARI buku
KELOMPOKKAN BERDASARKAN penulis
KONDISI COUNT(*) > 1
JOIN Antar Tabel
Buat tabel kedua untuk kategori:
BUKA LAHAN kategori (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nama TEXT NOT NULL
)
BUKA LAHAN buku_kategori (
buku_id INTEGER,
kategori_id INTEGER
)
Lakukan LEFT JOIN:
PANEN b.judul, k.nama DARI buku b
GABUNG KIRI kategori k PADA buku_kategori bc
DIMANA bc.buku_id = b.id DAN bc.kategori_id = k.id
Transaksi ACID
SawitDB mendukung transaksi penuh sejak versi 3.0. Mulai transaksi dengan MULAI AKAD, konfirmasi dengan SAHKAN, atau batalkan dengan BATALKAN:
MULAI AKAD
TANAM KE buku (judul, penulis, harga, stok)
BIBIT ('Tenggelamnya Kapal van der Wijck', 'Hamka', 85000, 5)
PUPUK buku DENGAN stok=stok-1 DIMANA id=1
SAHKAN
Jika ada error di tengah transaksi, jalankan BATALKAN untuk memastikan semua perubahan di-rollback:
MULAI AKAD
TANAM KE buku (judul) BIBIT ('Data Sementara')
BATALKAN
Tidak ada baris yang tersimpan setelah BATALKAN dieksekusi.
Views dan Stored Procedures
Views dengan PASANG TEROPONG
Buat view untuk menyederhanakan query yang sering digunakan:
PASANG TEROPONG BukuTersedia SEBAGAI
PANEN judul, penulis, harga DARI buku DIMANA stok > 0
Akses view seperti mengakses tabel biasa:
PANEN * DARI BukuTersedia
Stored Procedures dengan SIMPAN SOP
Simpan prosedur yang bisa dipanggil ulang:
SIMPAN SOP TambahStok(buku_id INTEGER, jumlah INTEGER) SEBAGAI
PUPUK buku DENGAN stok = stok + jumlah DIMANA id = buku_id
Panggil prosedur dengan:
JALANKAN SOP TambahStok(1, 10)
Replikasi Primary-Replica
Untuk kebutuhan high availability, SawitDB mendukung setup Primary-Replica. Konfigurasikan replica dengan:
SETEL CABANG PRIMARY host=192.168.1.10 port=7878
Perintah ini menginstruksikan node saat ini untuk mereplikasi data dari primary yang ditentukan. Change Data Capture (CDC) juga tersedia untuk skenario streaming perubahan data ke sistem eksternal — aktifkan via environment variable:
SAWIT_CDC_FILE=./logs/sawit.cpo
SAWIT_CDC_ADAPTER=cpo
Fitur replikasi dan CDC didesain untuk deployment cluster. Untuk penggunaan single-node, fitur ini tidak diperlukan.
Perbandingan Singkat dengan Pendekatan Lain
| Aspek | SawitDB | SQLite | PostgreSQL |
|---|---|---|---|
| Setup | Zero config | Minimal | Server + config |
| Dependency | Tidak ada | Native binding | Client library |
| Query language | AQL + SQL | SQL | SQL |
| Network mode | TCP built-in | Tidak ada | Built-in |
| Replikasi | Built-in (v3+) | Tidak ada | Built-in |
| Cocok untuk | Proyek Node.js lokal | Embedded app | Production skala besar |
SawitDB mengisi ruang yang belum ditempati SQLite di ekosistem Node.js — tanpa native binding, dengan network mode bawaan, dan dengan sintaks yang memang dirancang untuk konteks lokal.
Kesimpulan
SawitDB membuktikan bahwa database yang andal tidak harus bergantung pada infrastruktur cloud yang mahal atau konfigurasi server yang rumit. Dengan AQL yang playful dan arsitektur yang solid — WAL, B-Tree index, ACID transaction, replikasi — ini adalah pilihan yang masuk akal untuk proyek Node.js yang butuh penyimpanan terstruktur tanpa overhead. Coba mulai dari mode lokal, dan skalakan ke mode server ketika kebutuhan bertambah.