Sqlite Storage

by val-town2d3ec654b6a7No licenseListed Oct 8, 2026Updated Oct 8, 2026

Use when a val needs to store structured or relational data. Covers the std/sqlite API, parameterized queries, transactions, and the val-scoped vs organization-scoped database distinction.

AI-generated overview

Guides use of Val Town's built-in SQLite storage for structured or relational data in vals.

What it does
This skill explains how to use the std/sqlite module in Val Town to store structured or relational data. It covers basic table creation and parameterized queries, atomic multi-statement transactions via sqlite.batch, and the difference between val-scoped and organization-scoped databases. It also notes how to target an organization-owned val when querying through the sqlite_execute or sqlite_batch tools, and lists rules for parameterization, idempotent schema setup, and migrations.
When to use it
Use it when a val needs persistent relational or structured data, such as users, tables, or queries. It is also relevant when deciding between val-scoped and organization-scoped databases, or when writing transactions and schema migrations. For simple key/value data, the skill points to std/blob instead.
Requirements
Requires the Val Town platform and its built-in std/sqlite module (imported from esm.town); no scripts ship with the skill. It is instructions only, and the referenced API docs are external.

SQLite Storage

Val Town provides built-in SQLite via the std/sqlite module. Reach for it whenever a val needs relational or structured persistent data. For simple key/value data, prefer std/blob instead.

Basic usage

ts
import { sqlite } from "https://esm.town/v/std/sqlite/main.ts";
await sqlite.execute(`CREATE TABLE IF NOT EXISTS users (  id INTEGER PRIMARY KEY,  name TEXT NOT NULL,  email TEXT UNIQUE)`);
await sqlite.execute({  sql: "INSERT INTO users (name, email) VALUES (?, ?)",  args: ["Alice", "[email protected]"],});
const result = await sqlite.execute("SELECT * FROM users");// result.rows = [{ id: 1, name: "Alice", email: "[email protected]" }]

Transactions

Use sqlite.batch for atomic multi-statement transactions — all succeed or all roll back:

ts
await sqlite.batch([  { sql: "INSERT INTO users (name, email) VALUES (?, ?)", args: ["Bob", "[email protected]"] },  { sql: "UPDATE users SET name = ? WHERE id = ?", args: ["Robert", 2] },]);

Per-val vs organization databases

The import path determines which database you get. Both expose the same @libsql/client API (execute, batch) and return rows as keyed objects (Record<string, unknown>[]):

  • std/sqlite/main.ts — val-scoped database, isolated to this val. The default for new vals, and what you almost always want.
  • std/sqlite/global.ts — organization-scoped database, shared across every val owned by the same account. (Your personal account counts as its own organization here, so this database is shared across all of your vals.)

Do not switch an existing val between these import paths — it changes which database the val reads and writes.

Querying org-owned vals via tools

When using the sqlite_execute or sqlite_batch tools to query a val owned by an organization (not your personal account), pass the org handle as the org parameter so the call hits the right database. Example: { sql: "SELECT * FROM users", org: "some-org" }. This only matters for the tool calls — code inside the val itself reads from its own database automatically.

Rules

  • Always use parameterized queries (the args field) for any value derived from user input. Never interpolate strings into SQL.
  • Use CREATE TABLE IF NOT EXISTS so schema setup is idempotent across val restarts.
  • Schema migrations: add new columns with ALTER TABLE ... ADD COLUMN. Wrap in try/catch if the migration may run against an already-updated table.

Reference

Full API docs: https://docs.val.town/reference/std/sqlite/usage/

Source and attribution

Source:val-town/pluginsinplugin/skills/sqlite-storageat commit2d3ec65

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal