SQLite · served from S3

A SQL database you reach over HTTPS.

Every acknowledged write is in object storage before the response leaves the building.

No driver to install. One HTTPS request per statement.

receipt — one write
POST /v1/databases/db_production/query
{ "sql": "INSERT INTO events (kind) VALUES (?)",
  "params": ["signup"] }
{
  "columns": [],
  "rows": [],
  "rowsAffected": 1,
  "lastInsertRowid": 1,
  "epoch": 3,
  "txid": 412,
  "durability": "durable",
  "waitedMs": 118
}
DURABLEin object storage
  1. 1 write segment PUT 32 ms
  2. 2 advance pointer PUT
  3. ack returned p50 119 ms

Measured on the deployed stack, not estimated.

What this is

No connection pool

One HTTPS request per statement. No sockets to keep warm, no pool to size, no driver to install — which is what makes it usable from a serverless function that lives for 200 ms.

Real SQLite

Actual SQLite, not a wire-compatible reimplementation. Your indexes, RETURNING, window functions, CTEs, and foreign keys all behave the way the SQLite documentation says.

Honest about latency

A durable write costs about 120 ms, because it is two sequential round trips to object storage. Reads served from the owning worker are sub-millisecond.

Honest about failure

There is exactly one ambiguous outcome in the whole API, and it is named rather than hidden behind a retry.

The contract

What a 200 means

The bytes covering that write are in object storage. Not in a buffer, not on one machine’s disk, not queued for replication.

If every machine we run were destroyed the instant after you received the response, that write would still be there when a replacement came up.

The response says so explicitly — durability, txid, epoch, waitedMs — and the same three facts come back as headers, so a client that only reads headers does not have to parse the body.

Read Durability before you build on this →
Latency, measured
Measurementp50p95
Durable write, one transaction per batch119 ms157 ms
Read served by the owning worker< 1 ms< 1 ms
A raw 4 KB PUT to the same bucket32 ms38 ms

Object storage answers a single PUT in about 32 ms, yet a commit takes 119 — a commit is two sequential round trips.

Is this the right database for you?

Good fit

  • Read-heavy workloads with modest write rates
  • Per-tenant or per-user databases
  • Edge and serverless applications that cannot hold a connection
  • Anything where you want SQL and a durability story you can actually explain to an auditor

Bad fit, today

  • Write-heavy workloads that need sub-10 ms commits — the two round trips to object storage are a floor, not a tuning problem
  • Interactive transactions held open across requests; the atomic unit here is one batch
  • More than one writer per database, which is a correctness boundary rather than a limit we have not got round to raising

Quickstart

Five requests, then you’re a customer of your own database.

Everything below is plain curl against the live API. If you do not have a token yet, sign up, create a database, and create a key on it.

  1. 1 Create a database

    curl $BASE/v1/databases -d '{"name":"production"}'
  2. 2 Create a table

    {"sql":"CREATE TABLE events (id INTEGER PRIMARY KEY, …)"}

    DDL is a write like any other — durable by the time you read this.

  3. 3 Write a row

    {"sql":"INSERT INTO events (kind) VALUES (?)","params":["signup"]}

    Always bind values rather than interpolating them into the SQL.

  4. 4 Read it back

    {"sql":"SELECT id, kind FROM events ORDER BY id"}

    Rows are arrays, not objects — duplicate column names are legal SQL.

  5. 5 Do several things atomically

    POST /v1/databases/$DB/batch — three statements cost ~120 ms

    The latency is one round trip per batch, not per statement. Batch aggressively.

SQL, with a durability story you can explain to an auditor.