Skip to content
AOZUMIDocs

Connect from your code

Your code needs two values: the server URL and a token for one database. Get them from the database's page in the AOZUMI DB console, or, for an app, AOZUMI sets them for you.

The two variables

.env
AOZUMI_DB_URL=https://db.aozumi.dev
AOZUMI_DB_TOKEN=adb1.…
  • Standalone database: on its page, select Show token and copy both lines. See Tokens and access.
  • An app's database: AOZUMI sets both variables in the app's environment. Redeploy the app to connect. See Databases for your apps.

@libsql/client

Install it with npm install @libsql/client. AOZUMI tests against version 0.18.

db.ts
import { createClient } from "@libsql/client";

const db = createClient({
  url: process.env.AOZUMI_DB_URL!,
  authToken: process.env.AOZUMI_DB_TOKEN,
});

await db.execute({
  sql: "insert into notes (body) values (?)",
  args: ["hello"],
});
const { rows } = await db.execute("select * from notes");

Drizzle

Use Drizzle's libSQL driver, drizzle-orm/libsql, with the same two values.

db.ts
import { drizzle } from "drizzle-orm/libsql";
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";

const notes = sqliteTable("notes", {
  id: integer("id").primaryKey(),
  body: text("body").notNull(),
});

const db = drizzle({
  connection: {
    url: process.env.AOZUMI_DB_URL!,
    authToken: process.env.AOZUMI_DB_TOKEN,
  },
});

await db.insert(notes).values({ body: "hello" });
const rows = await db.select().from(notes);

Plain HTTP

Any language can send a pipeline of requests to /v2/pipeline with the token as a bearer token.

Terminal
curl "$AOZUMI_DB_URL/v2/pipeline" \
  -H "Authorization: Bearer $AOZUMI_DB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requests": [
        {"type": "execute", "stmt": {"sql": "select * from notes"}},
        {"type": "close"}
      ]}'

A pipeline accepts execute, batch (with conditions), sequence, store_sql, close_sql, get_autocommit and close. GET /v2 checks the protocol version.

Transactions

A batch runs its statements together: if one fails, none of them are kept.

db.ts
await db.batch([
  { sql: "insert into lists (name) values (?)", args: ["Groceries"] },
  { sql: "insert into items (list, body) values (last_insert_rowid(), ?)", args: ["Milk"] },
], "write");

Interactive transactions, where your code reads and then decides what to write, also work: db.transaction() in @libsql/client keeps one session open across requests.

What is not supported

  • WebSockets. Use an https:// URL.
  • Hrana v3, including cursors and protobuf, and the describe request.
  • Attaching other databases, VACUUM INTO, and most PRAGMA statements. See refused SQL.

Errors your code can see

ErrorWhat it means
SQLITE_FULLThe database reached its size limit. Delete data you no longer need.
SQLITE_INTERRUPTA statement ran longer than 5 seconds and was stopped. Add an index or split the work.
SQLITE_READONLYThe token is read only, and the statement writes.
SQLITE_AUTHThe statement is not allowed, such as ATTACH or an unsafe PRAGMA.
HTTP 401The token is wrong, or it was revoked by a rotation. Get the new one.
HTTP 429More than 100 requests a second reached this database. Wait for Retry-After, then try again.

Questions

Which URL do I use for each database?
The same one for all of them: https://db.aozumi.dev. The token decides which database a request opens.
Does AOZUMI DB support WebSockets?
No. The server answers over HTTPS only. Use an https:// URL with your client so it does not try a WebSocket connection.
Can I use it from Python, Go or Rust?
Any client that speaks libSQL's HTTP protocol (Hrana v2 over JSON) should work, but AOZUMI has only tested @libsql/client, Drizzle and plain HTTP so far.

Checked against the product on .