Migrate Val Town SQLite
Export a val's std/sqlite database and import it into Turso.
Easel doesn't host databases, and a function can't keep a SQLite file between
requests. Move std/sqlite data to Turso, which runs the
same libSQL engine, so most queries work unchanged.
Export from Val Town
Before December 10, 2026, add this exporter as a new HTTP file in the val that
owns the database, and set a random SQLITE_EXPORT_TOKEN in the val's
environment variables. List the app's tables in TABLES, parent tables first.
For an account-wide database, import from https://esm.town/v/std/sqlite/global.ts
instead.
sqlite-export.ts
Download the export and restore it locally:
The last line of app.sql must be -- export complete, and the integrity check
prints ok. Pause writes and cron jobs while you export, since the export isn't
a snapshot. Full-text search tables aren't exported; recreate them after the
import.
Import into Turso
Add the URL and token to the project's Preview environment as
TURSO_DATABASE_URL and TURSO_AUTH_TOKEN.
Update the queries
Install @libsql/client and replace the std/sqlite import:
getDb().execute takes the same arguments as sqlite.execute, and rows can be
read by name or index. Rows aren't arrays, though: code written for an
account-wide database that destructures rows, like const [id, title] = row,
needs row[0] or row.id instead.
Verify
Compare the restored file with the Turso database. This script prints a row count and hash per table, and both outputs must match:
hash-tables.mjs
Switch to production
Freeze writes on Val Town, take a fresh export, and create the production
database from it, such as turso db create link-shelf --from-file ./app.db.
Run the hash check again, then set the production credentials on the project's
Production environment. Keep the export as a backup.
To move to Postgres instead, convert the restored file with
pgloader and expect to rewrite SQLite-specific queries.
Back to the feature list.