// a query is a pure, reactive read
export const list = query({
args: { channelId: v.id("channels") },
handler: (ctx, { channelId }) =>
ctx.db.query("messages", "by_channel")
.eq("channelId", channelId).collect(),
});
// on the client, re-renders when a mutation commits
const messages = useQuery(api.messages.list, { channelId });Open source · self-hosted
The reactive backend you run yourself.
Write your backend as TypeScript queries and mutations. Subscribe once, and helipod pushes fresh results to every client the moment the data changes. No polling, no refetching.
Data changes push themselves
Every query records what it read; every write is checked against it.
8.6ms
Median reactive propagation in a same-substrate benchmark. Run it yourself before you trust it.
See the numbersAuth, scheduler, workflows
Opt-in components: authentication, cron and scheduled jobs, durable multi-step workflows with saga compensation, triggers, and notifications.
SQLite or Postgres, plus files
Zero-config SQLite for local, Postgres when you need it, and built-in blob storage on the filesystem or any S3-compatible bucket.
Optimistic and offline
A typed client with instant optimistic updates and a durable offline outbox that survives reloads, with exactly-once delivery on reconnect.
Actions, HTTP, crons
Actions run outside the transaction for fetch, timers, and randomness. Public HTTP endpoints handle webhooks.
A live data browser
Browse and edit tables, watch logs, and run functions from a built-in dashboard that updates reactively.
Runs where you run
One command in development. In production it is a single self-contained binary, a Docker image, or a Cloudflare deployment, backed by your own SQLite file or Postgres. No managed cloud in the loop, no vendor lock-in.
What it doesn't do yet
- No searchQuery by index and range. Full-text and vector are reserved seams.
- Single-node writesOne writer per shard. Multi-node scale-out is a later tier.
- No built-in TLSPlain HTTP. Front it with nginx, Caddy, or Traefik.
- In-process functionsA V8-isolate sandbox for untrusted code is a reserved seam.
Write your first reactive function in a few minutes.
The quickstart takes you from an empty folder to a live, reactive app.
Start building →