2026-08-01 · 10 min
SQLite di Production 2026: Kapan Turso dan libSQL Masuk Akal untuk SaaS Indonesia
Tiga bulan lalu saya bantu satu klien di Jakarta Selatan yang punya SaaS manajemen restoran: ratusan merchant, masing-masing dengan data terpisah, tim engineering dua orang. Pertanyaan mereka sederhana tapi konsekuensinya jauh: “Perlu tidak kita pakai Postgres untuk ini, atau SQLite dengan Turso cukup?”
Jawabannya tidak sesederhana pertanyaannya, tapi ada framework yang bisa saya bagikan dari pengalaman langsung di kondisi itu.
Konteks: mengapa SQLite kembali relevan di 2026
Selama bertahun-tahun, SQLite dianggap “database untuk development lokal dan mobile”. Production SaaS selalu diasumsikan butuh Postgres atau MySQL. Tapi 2025-2026 mengubah itu dengan beberapa faktor bersamaan:
- Turso dan libSQL menjadikan SQLite addressable lewat jaringan, dengan embedded replica yang bisa sinkron ke edge node
- Database per tenant sebagai pola arsitektur mendapat perhatian ulang, karena isolasi data lebih kuat dan query sederhana
- Edge computing (Cloudflare Workers, Fly.io) butuh database yang bisa hidup dekat dengan compute — SQLite file jauh lebih mudah dipindah dibanding connection pool Postgres
- Biaya operasional startup Indonesia makin terasa; tim kecil tidak sanggup urus Postgres cluster sendiri dengan benar
Yang paling menarik dari libSQL adalah ia mempertahankan kompatibilitas SQL penuh dengan SQLite, tapi menambahkan networking layer yang sebelumnya tidak ada. Artinya, query Anda tidak perlu diubah.
Pola yang cocok: database per tenant
Inilah kondisi di mana Turso paling masuk akal untuk SaaS Indonesia skala kecil. Alih-alih satu Postgres besar dengan semua tenant di dalamnya (dipisahkan oleh tenant_id), setiap tenant dapat database SQLite sendiri.
Keuntungannya nyata:
- Isolasi sempurna — satu tenant tidak bisa bocor ke tenant lain secara definitif, bukan hanya lewat row-level policy
- Migration per tenant bisa dilakukan bertahap tanpa lock global
- Menghapus tenant tinggal drop satu database file, bukan
DELETE FROM ... WHERE tenant_id = ...yang bisa merusak data lain kalau ada bug - Query sederhana — tidak perlu setiap query membawa
WHERE tenant_id = $1, jadi kode lebih bersih dan risiko data leak berkurang
Setup awal dengan Turso SDK di Node.js:
import { createClient } from '@libsql/client';
// Tiap tenant dapat database URL sendiri
function getTenantDb(tenantSlug: string) {
return createClient({
url: `libsql://${tenantSlug}-yoursaas.turso.io`,
authToken: process.env.TURSO_AUTH_TOKEN,
});
}
// Penggunaan
const db = getTenantDb('warung-pak-budi');
const result = await db.execute('SELECT * FROM orders WHERE status = ?', ['pending']);
Untuk membuat database baru saat tenant mendaftar, Turso menyediakan Management API:
import { createClient as createTursoClient } from '@tursodatabase/api';
const turso = createTursoClient({
token: process.env.TURSO_API_TOKEN,
org: 'yoursaas',
});
async function provisionTenantDatabase(tenantSlug: string): Promise<string> {
const db = await turso.databases.create(tenantSlug, {
group: 'default',
schema: 'shared-schema', // mengikuti skema terpusat
});
return db.hostname;
}
Kombinasi schema database di Turso adalah fitur yang paling menghemat waktu: Anda mendefinisikan skema sekali, semua tenant database mengikutinya. Saat ada migration, jalankan di schema database, Turso propagasi ke semua child secara otomatis.
Setup embedded replica untuk latency rendah
Kalau aplikasi Anda berjalan di VPS Hetzner di Frankfurt atau bahkan Singapore, round-trip ke Turso tetap ada overhead. Untuk workload read-heavy, embedded replica sangat membantu: database SQLite disimpan lokal di server Anda, sinkron dari Turso, dan read dilayani dari lokal tanpa network call.
import { createClient } from '@libsql/client';
import path from 'node:path';
function getTenantDbWithReplica(tenantSlug: string) {
const localPath = path.join(process.env.DB_DIR!, `${tenantSlug}.db`);
return createClient({
url: `file:${localPath}`,
syncUrl: `libsql://${tenantSlug}-yoursaas.turso.io`,
authToken: process.env.TURSO_AUTH_TOKEN,
syncInterval: 60, // sinkron setiap 60 detik
});
}
Dengan pola ini, read langsung dari file lokal (sub-millisecond), write diteruskan ke Turso remote dan kemudian disinkronkan balik. Cocok untuk dashboard yang data-nya tidak perlu real-time ke detik.
Satu catatan praktis: direktori untuk file replica harus persistent. Kalau Anda deploy di container dan direktori tidak di-mount ke volume, replica hilang setiap restart dan harus full sync ulang. Di production kami, direktori ini ada di persistent volume terpisah dari container image.
Schema migration dengan banyak tenant
Untuk SaaS yang sudah jalan dan punya ratusan tenant, migration schema adalah momen paling kritis. Dengan model Turso schema database, ini jauh lebih mudah dari yang saya bayangkan pertama kali.
Struktur direktori migration yang saya pakai:
migrations/
001_create_orders.sql
002_add_payment_method.sql
003_add_index_status_created.sql
Jalankan migration ke schema database saja:
turso db shell shared-schema < migrations/003_add_index_status_created.sql
Turso otomatis propagasi ke semua child database. Tidak perlu script iterasi, tidak perlu urus concurrency. Ini adalah salah satu alasan saya merekomendasikan Turso dibanding self-hosted libSQL untuk tim yang tidak mau urus infrastruktur migration sendiri.
Untuk self-hosted, Anda perlu script seperti ini:
import { getAllTenants } from './tenant-store';
import { createClient } from '@libsql/client';
import { readFile } from 'node:fs/promises';
import pLimit from 'p-limit';
async function runMigrationAllTenants(migrationFile: string) {
const sql = await readFile(migrationFile, 'utf-8');
const tenants = await getAllTenants();
const limit = pLimit(10); // maks 10 database bersamaan
const results = await Promise.allSettled(
tenants.map(tenant => limit(async () => {
const db = createClient({ url: tenant.dbUrl, authToken: tenant.token });
await db.execute(sql);
return tenant.slug;
}))
);
const failed = results
.filter(r => r.status === 'rejected')
.map((r, i) => ({ tenant: tenants[i].slug, error: r.reason }));
if (failed.length > 0) {
console.error('Migration gagal untuk:', failed);
}
}
Batasi concurrency — saya pakai p-limit dengan nilai 10. Kalau Anda punya 500 tenant dan kirim 500 koneksi sekaligus, Anda akan throttle di API atau koneksi lokal.
Kapan jangan pakai SQLite/Turso
Saya ingin jujur soal batas ini, karena terlalu banyak artikel yang hanya menjual kelebihan tanpa mengakui kondisi di mana ini bukan pilihan tepat.
Jangan pakai database per tenant dengan SQLite kalau:
- Anda butuh JOIN lintas tenant secara rutin (laporan agregat, analytics global). Dengan model ini, query lintas tenant harus dilakukan di application layer — ambil dari masing-masing database lalu gabungkan di memori. Ini menyakitkan untuk data besar.
- Satu tenant Anda punya jutaan row dan traffic tinggi. SQLite punya writer lock — satu write pada satu waktu. Untuk tenant kecil ini tidak terasa, tapi untuk tenant besar dengan ratusan concurrent write, ini bottleneck.
- Tim Anda sudah mahir Postgres dan punya tooling monitoring yang matang (pgBadger, pg_stat_statements, Patroni). Berpindah ke ekosistem baru ada biaya pembelajaran dan debugging.
- Aplikasi Anda butuh fitur Postgres yang tidak ada di SQLite: full-text search dengan
tsvector,LISTEN/NOTIFY, advisory locks, atau extension sepertipgvectoruntuk AI feature.
Untuk klien Jakarta Selatan yang saya sebut di awal: mereka akhirnya pakai Turso. Alasannya konkret — dua engineer yang tidak punya bandwidth urus Postgres production dengan benar, model bisnis satu merchant satu database sangat clean, dan traffic per merchant masih rendah (puluhan transaksi per hari). Dengan Turso, mereka tidak perlu urus backup, replikasi, atau patching.
Kalkulasi biaya nyata
Turso free tier: 500 database, 9 GB storage, 1 miliar row reads/bulan. Untuk fase awal dan ratusan merchant kecil, ini gratis.
Begitu skala ke ribuan tenant atau tenant mulai tumbuh besar, Turso Scaler USD 29/bulan memberikan 10.000 database dan storage lebih besar. Dibandingkan alternatif:
- VPS Hetzner CX22 (2 vCPU, 4 GB RAM) ~EUR 4/bulan, tapi Anda urus sendiri backup, monitoring, failover
- Supabase Pro USD 25/bulan, Postgres managed, tapi satu database untuk semua tenant (butuh RLS)
- Neon Postgres Scale USD 69/bulan untuk branching dan autoscale
Kalkulasi yang saya pakai: hitung jam engineer per bulan yang dihabiskan untuk operasional database. Untuk tim dua orang, bahkan 2 jam per bulan untuk maintenance Postgres sudah worth dibandingkan USD 29 untuk database managed yang tidak perlu disentuh.
Verdict
Turso dan libSQL masuk akal untuk SaaS Indonesia skala kecil dengan kondisi spesifik:
- Model database per tenant — ini kondisi terpenting. Kalau Anda masih pakai satu database dengan
tenant_id, tetap pakai Postgres dengan RLS. - Tim kecil tanpa DBA dedicated — managed Turso menghemat operasional signifikan.
- Tenant masing-masing kecil — traffic rendah sampai sedang per tenant, tidak ada yang dominan.
- Workload lebih banyak read — embedded replica sangat membantu latency.
- Tidak butuh fitur Postgres spesifik — kalau sudah pakai
pgvector,LISTEN/NOTIFY, atau full-text Postgres, biaya migrasi tinggi.
Kalau kondisi di atas terpenuhi, Turso adalah pilihan yang jujur dan pragmatis untuk 2026. Ekosistem libSQL sudah cukup mature, SDK tersedia untuk Node.js, Go, Rust, dan Python, dan Turso team aktif memperbaiki edge case. Ini bukan lagi eksperimen — beberapa SaaS production di Asia Tenggara sudah membuktikannya.
Yang perlu diingat: pilihan database adalah commitment jangka panjang. Migrasi dari SQLite ke Postgres di tengah jalan lebih sulit dari yang terlihat, terutama kalau Anda sudah punya ratusan tenant database yang harus dikonsolidasi. Putuskan di awal dengan kondisi yang jujur, bukan karena ikut tren.
Ditulis oleh Reza Pradipta