Chronos/DBWaitlist

Connect

Your app (Postgres)

Connect your application with DATABASE_URL, as to any Postgres, and point tests at a world.

SoonThese pages describe Chronos Cloud, which opens from the waitlist. Running Chronos yourself? Self-host docs

DATABASE_URL

Your app connects to its project’s database as to any Postgres 16, with the URL chronos init writes into .env (or Overview → reveal in the dashboard, which is logged):

.env
DATABASE_URL=postgres://app:<password>@<host>:5432/main?sslmode=require&options=endpoint%3Ddb_…
PartMeaning
appthe app’s role: it reads and writes tables (and makes them: migrations work), directly, outside merge policies and reviews, as an app must. It can’t make, merge or drop worlds, or change agents, rules or settings, so a leaked .env can’t either
<password>written to .env (readable only by you) and shown on reveal; the CLI never prints it
/mainthe world to connect to: the database name. Any world’s name works here
sslmode=requireTLS is required. A client that doesn’t ask for it gets FATAL 08P01 TLS required
options=endpoint%3Ddb_…which database, read from the startup message. libpq, psycopg, node-postgres and most drivers pass it on from the URL

Drivers and ORMs

Node: node-postgres

db.ts
import pg from 'pg';export const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL, max: 10 });const { rows } = await pool.query('select id, email from users where id = $1', [id]);

Prisma

schema.prisma
datasource db {  provider = "postgresql"  url      = env("DATABASE_URL")}

Run prisma migrate deploy against a world first (its name in place of main), check the diff, then merge, rather than migrating main directly.

Drizzle

db.ts
import { drizzle } from 'drizzle-orm/node-postgres';export const db = drizzle(process.env.DATABASE_URL!);

Python: psycopg 3

db.py
import os, psycopgwith psycopg.connect(os.environ["DATABASE_URL"]) as conn:    rows = conn.execute("select id, email from users where id = %s", (user_id,)).fetchall()

SQLAlchemy

db.py
from sqlalchemy import create_engineengine = create_engine(os.environ["DATABASE_URL"].replace("postgres://", "postgresql+psycopg://", 1))

psql and GUI tools

terminal
psql "$DATABASE_URL"\dt                       -- tables, as in Postgresselect * from orders as of '-10 minutes' limit 5;   -- and Chronos's reads

A tool that asks for host, port, user and database separately: put the database’s id (db_…) as the endpoint option, or use the whole URL. If a driver drops options, the server answers with an error that says the endpoint is missing: set the option in that driver’s connection settings.

Connecting to a world

The database name is the world. To run the app or its tests against an agent’s world, change /main to its name; nothing else changes, and main never sees what the tests write.

terminal
WORLD=add-plansDATABASE_URL=$(echo "$DATABASE_URL" | sed "s#/main?#/$WORLD?#") npm test

A name with characters a URL treats specially goes percent-encoded. A world that doesn’t exist refuses the connection with 3D000.

Connecting to the past

A database name of the form world@when connects to the world as it was, read only (a write fails with 25006): main@-1 hour, main@2026-10-20 09:00. Percent-encode it in a URL (main%40-1%20hour). Within a query, read one table as it was with AS OF instead; see Time travel.

Transactions

  • READ COMMITTED is the default, as in Postgres; REPEATABLE READ is supported, with row locks that wait as Postgres’s do. SERIALIZABLE is refused (0A000) rather than given weaker guarantees under its name.
  • Outside a transaction each statement commits on its own, on disk before it returns.
  • World statements (CREATE, MERGE, DROP WORLD, RESTORE, …) can’t run inside BEGIN … COMMIT (25001).
  • Prepared statements, COPY, LISTEN/NOTIFY, cursors and the extended protocol work as in Postgres.

Sleeping and waking

On the free plan a database sleeps after 5 minutes with no connections, and wakes on the next one: that first connection takes a moment longer. Awake time counts against the plan’s monthly hours. Pools that hold connections open keep it awake; set an idle timeout on the pool if the app is idle for long stretches.

Limits

LimitFree plan
connections at once50
storage per database512 MB
data out a month5 GB
awake time a month100 hours

See Plans and limits for what happens at each limit.

Your app (Postgres) · Chronos