v2.7.1 · MIT · npm: @larva-db/core
A real SQL database, living in your object store
Larva turns Vercel Blob, S3, or R2 into a durable SQL database with transactions, time travel, and a Postgres escape hatch. No server to run, no connection string to leak — just the bucket you already have.
297
automated checks on every push
1
CAS swap per commit — the whole write path
3
storage backends: Vercel Blob, S3, R2
0
servers, containers, connection strings
This page is a database. Query it.
A seeded demo store — customers, orders, sequence-numbered invoices — living in a private Vercel Blob store. Every run below hits it for real: watch the chunk pruning, the version counter, and the errors that teach.
Want to write to it, stress it, or time-travel through it? The test lab and data viewer run on the same store.
Schema in code. Queries in SQL. Nothing in between.
Define tables with typed columns and get inference for free — every row that comes back is already typed. Sequences and UUIDs assign themselves; a nullable column added in code migrates the store on connect.
The tagged template is the whole API: parameters are extracted, never concatenated, and multiple statements per string are rejected outright.
The entire API fits on one screen →import { defineSchema, larva, t } from "@larva-db/core";
const db = larva({
schema: defineSchema({
invoices: {
number: t.sequence().primaryKey(),
customer: t.text(),
total: t.real(),
createdAt: t.timestamp().partitionBy(),
},
}),
});
// typed rows out, params extracted — never concatenated
const [invoice] = await db.sql`
INSERT INTO invoices (customer, total)
VALUES (${name}, ${total})
RETURNING number, customer`;
// the database, ten minutes ago
const past = await db.asOf(new Date(Date.now() - 600_000));Small on purpose. Honest everywhere.
Real SQL
Joins, transactions, aggregates, upserts, subqueries, secondary indexes — a closed, documented dialect that is a strict subset of Postgres. What runs here runs there.
No lost writes. Ever.
Every commit is one compare-and-swap on the manifest. Concurrent writers rebase or re-run; after that, conflicts fail loudly. Silent data loss is a bug class Larva doesn’t have.
Time travel built in
Every commit is a complete snapshot. Query the database as of ten minutes ago, or roll back to any retained version — the rollback is itself undoable.
Built for AI agents
Unsupported SQL returns machine-readable errors that name the feature and the alternative, so agents self-correct. The whole manual ships at /llms.txt.
Private by construction
Every data blob is written private; Larva never mints a public URL for your rows. The only secret is the storage token you already have.
The escape hatch
larva export emits a pg_dump-shaped file — psql < export.sql is the whole migration. Outgrowing Larva is a supported feature, not a trap.
Delta Lake, miniaturized
The same architecture trusted for petabyte lakehouses, shrunk until it fits in a bucket: immutable data, one tiny mutable pointer, and optimistic concurrency on that pointer alone.
01
Rows live in immutable chunks
Gzipped JSON blobs, ULID-named, never modified after they're written. Updates produce replacement chunks — which is why caching them can never go stale.
02
One manifest describes everything
A single JSON file holds the schema, every table's chunk list, and zone-map stats for pruning. Its ETag is the concurrency token for the whole database.
03
A commit is one conditional swap
Stage new chunks (touches nothing live), then compare-and-swap the manifest. Losers rebase if disjoint, re-execute if overlapping, and fail loudly after that.
Read how it works — including what it deliberately doesn’t do →
Building with an agent? Hand it the manual.
The complete dialect, the error catalog, and the rules of thumb are served as one plain-text prompt at /llms.txt. Paste it into any agent and it writes correct Larva on the first try — and when it doesn’t, the error message is the documentation.

Your first table is one bun add and one token away.
