Skip to content

Flect db

Part of the flect skill set.

Flect databases are SQLite-compatible, powered by sqld (libsql). Each database is an isolated sqld namespace. env.db(binding) hands you an official @libsql/client already scoped to that namespace — no URL or token in your code.

Terminal window
flect db create my-db # prints the public ref for flect.toml
flect db list
flect db status <ref>
flect db delete <ref>

flect deploy also creates any database named in flect.toml that doesn’t exist yet.

[[databases]]
binding = "DB"
name = "my-db"
migrations_dir = "migrations" # optional: where your .sql files live
import { createEnv } from '@getflect/sdk'
const env = createEnv()
const db = await env.db('DB') // binding name from flect.toml
// SELECT (parameterized)
const { rows } = await db.execute('SELECT id, name FROM users WHERE active = ?', [1])
// INSERT / UPDATE / DELETE
await db.execute({ sql: 'INSERT INTO users (id, name) VALUES (?, ?)', args: [crypto.randomUUID(), 'Alice'] })
// Atomic batch
await db.batch([
{ sql: 'INSERT INTO posts (id, title) VALUES (?, ?)', args: [id, title] },
{ sql: 'UPDATE users SET post_count = post_count + 1 WHERE id = ?', args: [userId] },
])

Standard client → Drizzle works directly:

import { drizzle } from 'drizzle-orm/libsql'
const orm = drizzle(await env.db('DB'))

Don’t invent methods — it’s the real @libsql/client. Use db.execute / db.batch, not db.query().

The new SDK has no runMigrations — apply schema yourself. Keep .sql files in migrations_dir and run them on boot with the same client (idempotent DDL):

import { readFileSync, readdirSync } from 'node:fs'
for (const f of readdirSync('./migrations').filter(f => f.endsWith('.sql')).sort()) {
await db.executeMultiple(readFileSync(`./migrations/${f}`, 'utf8'))
}

Use CREATE TABLE IF NOT EXISTS. If a database can be reused across app versions, self-heal a changed shape (check PRAGMA table_info(...), recreate if stale).

Each request carries the resource’s sqld namespace as an x-namespace header, so a binding only ever reads/writes its own data — enforced by sqld, not convention.

Terminal window
flect dev # writes flect.local.json; createEnv() resolves DB locally

Local default is :memory:. For persistent local sqld, run ghcr.io/tursodatabase/libsql-server with --enable-namespaces and set DB_URL (see Local development).

  • SQLite write semantics apply (a single writer at a time).
  • flect-app — deploy the app that uses this DB.
  • flect-kv — pair a cache with the DB (cache-aside).
  • flect — the model, CLI, scopes.