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):
DATABASE_URL=postgres://app:<password>@<host>:5432/main?sslmode=require&options=endpoint%3Ddb_…| Part | Meaning |
|---|---|
app | the 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 |
/main | the world to connect to: the database name. Any world’s name works here |
sslmode=require | TLS 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
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
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
import { drizzle } from 'drizzle-orm/node-postgres';export const db = drizzle(process.env.DATABASE_URL!);Python: psycopg 3
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
from sqlalchemy import create_engineengine = create_engine(os.environ["DATABASE_URL"].replace("postgres://", "postgresql+psycopg://", 1))psql and GUI tools
psql "$DATABASE_URL"\dt -- tables, as in Postgresselect * from orders as of '-10 minutes' limit 5; -- and Chronos's readsA 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.
WORLD=add-plansDATABASE_URL=$(echo "$DATABASE_URL" | sed "s#/main?#/$WORLD?#") npm testA 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 COMMITTEDis the default, as in Postgres;REPEATABLE READis supported, with row locks that wait as Postgres’s do.SERIALIZABLEis 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 insideBEGIN … 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
| Limit | Free plan |
|---|---|
| connections at once | 50 |
| storage per database | 512 MB |
| data out a month | 5 GB |
| awake time a month | 100 hours |
See Plans and limits for what happens at each limit.