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
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.
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.
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.
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.
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
describerequest. - Attaching other databases,
VACUUM INTO, and mostPRAGMAstatements. See refused SQL.
Errors your code can see
| Error | What it means |
|---|---|
SQLITE_FULL | The database reached its size limit. Delete data you no longer need. |
SQLITE_INTERRUPT | A statement ran longer than 5 seconds and was stopped. Add an index or split the work. |
SQLITE_READONLY | The token is read only, and the statement writes. |
SQLITE_AUTH | The statement is not allowed, such as ATTACH or an unsafe PRAGMA. |
HTTP 401 | The token is wrong, or it was revoked by a rotation. Get the new one. |
HTTP 429 | More 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 .