Aplikasi SvelteKit tidak harus memakai Turso Cloud untuk menggunakan Turso. Paket @tursodatabase/database dapat membuka file database langsung dari proses Node.js:

import { connect } from '@tursodatabase/database';

const db = await connect('local.db');

Konfigurasi ini tidak memerlukan URL database, authentication token, ataupun network round trip. Aplikasi membaca dan menulis file database lokal.

Pembedaan ini penting karena Turso memiliki paket terpisah untuk model eksekusi yang berbeda. Koneksi cloud dan database embedded menyelesaikan persoalan deployment yang berbeda meskipun keduanya menyediakan API SQL yang familiar.

Simpan database di balik batas server SvelteKit

Database embedded seharusnya berada di kode server-only. Struktur yang praktis adalah:

src/
├── lib/
│   └── server/
│       └── db.ts
└── routes/
    └── users/
        ├── +page.svelte
        └── +page.server.ts

Menempatkan modul koneksi di $lib/server mencegahnya diimpor ke kode browser melalui batas modul normal SvelteKit.

// src/lib/server/db.ts
import { connect } from '@tursodatabase/database';

export const db = await connect('local.db');

Server load function kemudian dapat menjalankan query secara langsung:

// src/routes/users/+page.server.ts
import { db } from '$lib/server/db';

export async function load() {
  const stmt = db.prepare(
    'SELECT id, name FROM users ORDER BY id DESC'
  );

  return { users: stmt.all() };
}

Browser menerima hasil yang sudah diserialisasi oleh SvelteKit. Browser tidak pernah membuka file database secara langsung.

Lokal berarti lokal terhadap proses server

Nama file yang diberikan ke connect menunjuk storage pada mesin yang menjalankan SvelteKit. Di laptop, database berada di laptop tersebut. Di container, file berada di dalam container kecuali direktorinya ditopang volume yang di-mount. Di VPS, file berada di VPS itu.

Arsitekturnya menjadi:

browser
   |
   v
server SvelteKit
   |
   | akses file lokal
   v
local.db

Tidak ada network hop menuju database. Konsekuensinya, umur filesystem menjadi bagian dari arsitektur data aplikasi.

Tempatkan operasi tulis di server action

Form action dapat menulis ke database embedded tanpa mengekspos akses database ke client:

// src/routes/users/+page.server.ts
import { fail } from '@sveltejs/kit';
import { db } from '$lib/server/db';

export const actions = {
  create: async ({ request }) => {
    const form = await request.formData();
    const name = String(form.get('name') ?? '').trim();

    if (!name) {
      return fail(400, { name, missing: true });
    }

    const stmt = db.prepare(
      'INSERT INTO users (name) VALUES (?)'
    );

    stmt.run([name]);

    return { success: true };
  }
};

Parameter binding penting pada bagian ini. Input pengguna sebaiknya diberikan sebagai value, bukan digabungkan ke string SQL.

Inisialisasi schema mengikuti batas server-only yang sama. Aplikasi kecil dapat membuat tabel secara eksplisit saat startup, sedangkan aplikasi yang lebih besar biasanya lebih tepat memakai migration berurutan agar perubahan schema dapat direproduksi.

Turso embedded berbeda dari Turso Cloud

Untuk storage lokal, dependency yang digunakan adalah:

npm install @tursodatabase/database

dan koneksinya berorientasi pada file:

import { connect } from '@tursodatabase/database';

const db = await connect('local.db');

Materi Turso saat ini menggunakan @tursodatabase/serverless untuk akses cloud remote secara langsung. Koneksi tersebut menerima URL remote dan authentication token.

Keduanya memiliki batas yang berbeda:

@tursodatabase/database
    -> database embedded
    -> file lokal
    -> tidak memerlukan akun Turso Cloud

@tursodatabase/serverless
    -> database remote
    -> koneksi network
    -> URL Turso Cloud + authentication

Database embedded tidak memakai kuota database Turso Cloud hanya karena engine database berasal dari Turso. Turso menyatakan penggunaan embedded gratis, sedangkan layanan cloud yang di-host memiliki paket dan limit tersendiri.

Deployment adalah batas yang paling penting

Development lokal dapat menyamarkan sifat terpenting embedded storage: database hanya bertahan jika filesystem-nya bertahan.

Proses Node.js yang berjalan terus-menerus di VPS cocok dengan model ini:

VPS
├── proses Node SvelteKit
└── /var/lib/myapp/local.db

Container juga dapat digunakan jika direktori database memakai persistent storage:

container
   |
   +-- aplikasi
   |
   +-- /data -> persistent volume
                 |
                 +-- local.db

Filesystem serverless yang ephemeral berbeda. Sebuah function instance dapat hilang, instance lain dapat dimulai dengan filesystem berbeda, dan beberapa instance belum tentu berbagi satu file lokal. Write yang berhasil pada satu instance karena itu tidak dapat dianggap sebagai shared state yang durable.

Ini bukan kekurangan SvelteKit atau database driver. Masalahnya adalah ketidakcocokan antara model storage database embedded dan model filesystem platform hosting.

Beberapa instance berarti beberapa database lokal

Misalnya service ditingkatkan menjadi tiga instance independen:

load balancer
  |    |    |
  v    v    v
 app  app  app
  |    |    |
 db1  db2  db3

Itu adalah tiga database, bukan satu database. Row yang dimasukkan melalui instance pertama tidak otomatis muncul pada dua instance lainnya.

Embedded storage cocok ketika aplikasi memang dirancang memiliki satu node durable, satu database per node, atau desain lain yang sengaja memberikan kepemilikan data secara lokal. Jika setiap instance harus melihat dataset authoritative yang sama, gunakan shared storage atau arsitektur database remote. Jangan menganggap file lokal independen akan menyatu dengan sendirinya.

Sync adalah keputusan arsitektur terpisah

Turso juga menyediakan @tursodatabase/sync. Paket ini mempertahankan database lokal sekaligus menambahkan sinkronisasi dengan database Turso remote:

import { connect } from '@tursodatabase/sync';

const db = await connect({
  path: 'local.db',
  url: process.env.TURSO_DATABASE_URL!,
  authToken: process.env.TURSO_AUTH_TOKEN!
});

Read dan write tetap dapat dilakukan secara lokal, sedangkan push() dan pull() bertukar mutation dengan database remote.

Model ini berguna ketika eksekusi lokal diperlukan tetapi data juga harus berpindah antarmesin. Sinkronisasi tidak perlu ditambahkan hanya karena aplikasi memakai embedded storage; sinkronisasi membawa persoalan konektivitas, conflict, dan operasionalnya sendiri.

Untuk service SvelteKit yang membutuhkan satu database lokal durable, @tursodatabase/database menjaga arsitektur tetap lebih kecil. Pertanyaan production yang menentukan bukan apakah connect(’local.db’) dapat berjalan. Pertanyaannya adalah apakah host menjamin file database yang sama masih tersedia, dan tetap merupakan file database yang benar, ketika request berikutnya datang.