karawaci.kode

2026-05-25 · 6 min

SQLite + Litestream: Database untuk SaaS Kecil dengan Budget 0

Saya punya SaaS kecil — alat invoice untuk freelancer Indonesia. Pelanggan: 47 aktif, ARR ~$3500. Margin tipis. Setiap pengurangan biaya infrastructure langsung jadi profit.

Enam bulan lalu, biaya database saya: $25/month untuk Hetzner managed Postgres. Tidak banyak tapi tidak nol.

Sekarang: $0. Migrasi ke SQLite + Litestream untuk replication ke Cloudflare R2.

Setup

# Dependencies
bun add better-sqlite3
brew install litestream  # macOS dev
# Production: download binary dari litestream.io

# litestream.yml
dbs:
  - path: /var/lib/myapp/data.db
    replicas:
      - type: s3
        bucket: myapp-backup
        endpoint: https://xxx.r2.cloudflarestorage.com
        path: data.db
        retention: 720h  # 30 days
        sync-interval: 10s
// Application code
import { Database } from 'bun:sqlite';

const db = new Database('/var/lib/myapp/data.db');
db.exec('PRAGMA journal_mode = WAL;');
db.exec('PRAGMA synchronous = NORMAL;');
db.exec('PRAGMA cache_size = -64000;'); // 64MB cache
db.exec('PRAGMA temp_store = MEMORY;');
db.exec('PRAGMA mmap_size = 268435456;'); // 256MB

export default db;
# systemd service
[Unit]
After=network.target

[Service]
ExecStart=/usr/local/bin/litestream replicate
Restart=always
User=myapp

[Install]
WantedBy=multi-user.target

Total: ~30 lines of config. Done.

6 bulan production stats

Database size: 240MB (47 aktif customer, 12K invoice). Read throughput: ~150 req/sec sustained, peak 800 req/sec. Write throughput: ~12 req/sec sustained. Replication lag to R2: 10-15 detik avg (sesuai sync-interval). Downtime: 0 (sekali server reboot, app continue setelah systemd restart).

Memory footprint: 80MB (vs Postgres ~250MB). Disk I/O: 30% dari Postgres yang sama.

Yang TIDAK bisa SQLite

  1. Multiple writers concurrent: WAL mode allows multi-reader + single-writer. Untuk OLTP heavy write: bukan match. Saya hanya 12 write/sec, fine.

  2. Network access: SQLite is in-process. App harus di-server yang sama. Tidak bisa “connect to database server”.

  3. Complex JSON query: SQLite JSON1 OK untuk dasar. Tapi tidak sebagus Postgres jsonb dengan GIN index. Untuk app yang heavily query nested JSON: stuck dengan Postgres.

  4. Stored procedures: SQLite has no procedural language. Logic must be di app code.

Yang Litestream beri

  1. Point-in-time recovery (PITR): bisa restore ke timestamp manapun dalam retention window (30 days untuk saya).
  2. Disaster recovery: kalau VPS hancur, restore dari R2 ke server baru ~5 menit.
  3. Read replica?: Litestream support replica server (litestream restore + read-only mode). Saya belum perlu, tapi opsi terbuka.

Cost breakdown

ItemOld (Postgres)New (SQLite + Litestream)
Database compute$25/mo (Hetzner managed)$0 (in-process)
StorageIncluded$0.015/mo (240MB R2)
BandwidthIncluded$0 (R2 egress free)
Backup tool$0$0 (Litestream OSS)
Total$25/mo~$0.02/mo

Saving: $24.98/mo = $300/year.

Untuk SaaS dengan ARR $3500, $300/year savings ~9% margin gain.

Kapan SQLite bukan match

  • Multi-region deploy yang butuh latency rendah dari berbagai benua.
  • App OLTP dengan > 100 writes/sec sustained.
  • Tim besar yang butuh DBA workflow (migration, schema review).

Saran

Kalau Anda jalankan SaaS kecil yang stuck dengan biaya managed DB: migrasi ke SQLite layak dipertimbangkan. 30 menit setup. Komitmen rendah untuk rollback (export SQLite ke Postgres adalah trivial).

Kalau klien Anda demand “real database” — kasih dia Postgres untuk peace of mind, tapi internal dashboard / project pribadi: SQLite cukup.

Yang killer fitur SQLite: WAL mode + Litestream + R2 = setup 30 menit, biaya nyaris nol, durability acceptable untuk most use case.

Ditulis oleh Reza Pradipta