Run it on your machine.
Clone and configure
Copy
.env.exampleto.env. The defaults run on one machine.Start it
docker compose up -d --wait. You need Docker Engine 26 and Compose 2.30 or newer, nothing else.Claim it
Read the setup code from the logs and create the first account with it: that account is the instance's admin.
Create a database
Open Studio, add a database, branch it and query it.
git clone https://github.com/chelabase/chelabase.git
cd chelabase/infra/compose
cp .env.example .env
docker compose up -d --wait
docker compose logs init-secrets # your setup code
# want a populated demo? add -f docker-compose.example.yml
# then open http://studio.chelabase.localhost:8000Everything in one place.
Every Chelabase backend service is built in Rust, and so is Neon's storage engine under Postgres: small native services that run together on one machine.
Databases
Postgres 17, each database with its own tenant and timeline and each branch its own compute, on Neon's storage engine. Postgres clients connect through its proxy with login roles.
Studio
The web console for all of it: projects, databases, the branch tree, the table and SQL editors, members, keys and your app's users.
Auth
Signs in Studio members and your app's own users, with helpers for row-level security policies.
Realtime
Pushes changed rows and presence over a WebSocket as keys only, so each row is read again as the viewer's role.
Gateway
The single front door. It checks every request's credential, a member's token or a data API key, and forwards it to the right service.
Orchestrator
Serves the Management API, decides who may do what, and keeps the platform's own state.
Worker
Runs the orchestrator's jobs: creating, branching, resetting, merging and deleting databases.
Rest
The data API. It turns a JSON query into SQL and runs it as the key's role, so row-level security decides what each caller sees.
CLIComing soon
A script you install for quick setup and management from the terminal: generate types, run migrations and more. Not available yet.
Object storageComing soon
S3-compatible storage for your app's files, planned on SeaweedFS, which already holds Neon's data in the stack. Not available yet.
The crab is a nod to Ferris, Rust's mascot. Chela is Greek for claw.
How it compares.
What each platform offers today, from its own docs. Benchmarks come later.
Comparison preview — benchmarks coming later
| Chelabase | Supabase | Firebase | Neon | PlanetScale Postgres | PlanetScale MySQL | |
|---|---|---|---|---|---|---|
| Postgres | Yes | Yes | Different model | Yes | Yes | Different model |
| Copy-on-write branches | Yes | Different model | No | Yes | No | No |
| Schema merge between branches | Yes | Partly | No | No | No | Yes |
| Point-in-time restore | Yes | Yes | Yes | Yes | Yes | No |
| Protected branches | Yes | No | No | Yes | Partly | Yes |
| Self-hostable | Yes | Partly | No | No | No | No |
| Typed query API | Yes | Yes | Different model | Yes | No | No |
| App-user auth, server rendering included | Yes | Yes | Yes | Yes | No | No |
| Team access through Postgres roles | Yes | Different model | Different model | Different model | Different model | Different model |
| Table and SQL editors | Yes | Yes | Partly | Yes | Partly | Partly |
| Live rows | Yes | Yes | Yes | Partly | No | No |
| Object storage | Coming soon | Yes | Yes | Yes | No | No |
From each product's docs, October 2026. Supabase's merge requests and Neon's realtime are in beta; Neon's schema diff compares branches but doesn't merge them. PlanetScale merges schema through deploy requests on MySQL (Vitess) only.
Manage it from one console.
Studio holds the whole database: tables, SQL, roles, keys and your app's users. A change shows as the SQL it will run, before it runs.
Structure changes you can read first
The table editor stages column, index and constraint changes, shows them as the exact SQL with a dry run, and applies them in one transaction.
A SQL editor with a guard
It asks before risky statements, runs as the owner or as a role you pick, and keeps saved queries and history for the project.
Credentials you can see again
Login role passwords are encrypted at rest and can be revealed later, so a lost connection string doesn't mean a reset.
Security in plain view
Studio flags tables the data API can reach without row-level security, and says when you're running as the owner.
Bring your team in.
Invite people, group them into teams, and grant each team the Postgres roles it may act as. Postgres' own privileges decide the rest, so a schema can belong to one team.
Teams with live grants
Change a team's grant and every member changes with it. Per-database overrides narrow it for one person.
Protected branches
Protect a branch from delete and reset. Protecting first reviews any code an untrusted role could run in an Admin's session.
Work side by side
The table editor shows live rows and who else is looking, and a save fails rather than overwrite someone's change.
An access log
Every invite, grant, approval and removal is recorded with who did it and what changed, never secrets.
Build your app on a typed API.
One endpoint, POST /data/v1/query, and a client with types fetched from your schema. Queries run as anon or authenticated, so row-level security decides what each user sees.
Auth for your app's users
Sign-up, sign-in and sessions, with helpers for row-level security policies.
Server rendering
Browser and server clients see the same signed-in user through cookies, and the refresh token stays HttpOnly.
Plain Postgres too
Migrations, ORMs and
psqlconnect over the Postgres protocol with a login role.
orders.tsimport { createServerClient } from "@chelabase/client/server";
import { type Database, types } from "./db";
// ./db comes from GET /data/v1/types
const db = createServerClient<Database>({ url, key, types, cookies });
const user = await db.auth.getUser();
const mine = await db
.from("orders")
.select("id", "total")
.where({ customer_id: user.id });
// sales.orders, only the signed-in customer's rowsBranch it. Reset it. Restore it. Merge it.
Every database starts with one branch, main. Try a change on a copy of real data, then bring it home.
Branch
Copy any branch as it is now, or as it was at any point in its history window (seven days by default). The copy is copy-on-write, so it's ready at once, with its own endpoint and password.
preview is a copy-on-write copy of main as it was 3 days ago. It shares main's pages until either side writes.
Start with the Quickstart.
Create a database, add a table, and query it from your app with the typed client.