On Runtime, a seeded database can be copied while it is running, in one call. Load the schema and fixtures once, then fork the sandbox. Every copy starts with Postgres already up and the data in memory. Ten tests or ten agent attempts each get a private database, without ten restores. Every sandbox is a Firecracker microVM. A sandbox that holds an idle database costs $0.03125 an hour for 2 vCPU and 4 GiB (pricing). Ubuntu 24.04 shipped PostgreSQL 16.15 on 25 October 2026. The PostgreSQL project's own apt repository listed 18 as its current stable release.
Start a database and load a schema
Ubuntu's package creates a cluster of its own. The sample drops that cluster and
creates one in /workspace, owned by the sandbox user. This way, nothing else
depends on how the system starts services.
TypeScriptimport { writeFile } from "node:fs/promises";import { Sandbox } from "withruntime";const bin = "/usr/lib/postgresql/16/bin";await using sbx = await Sandbox.create({ timeoutSeconds: 1800 });const slow = { check: true, timeoutMs: 600_000 } as const;await sbx.exec("sudo apt-get update -qq && sudo apt-get install -y -qq postgresql", slow);await sbx.exec("sudo pg_dropcluster --stop 16 main", { check: true });await sbx.exec(`${bin}/initdb -D /workspace/pgdata -U postgres --auth=trust`, slow);await sbx.spawn(`${bin}/postgres -D /workspace/pgdata -k /tmp -c listen_addresses=127.0.0.1`);await sbx.exec("timeout 60 bash -c 'until pg_isready -q -h 127.0.0.1; do sleep 0.5; done'", { check: true, timeoutMs: 90_000,});await sbx.files.upload("./schema.sql", "/workspace/schema.sql");const psql = "psql -h 127.0.0.1 -U postgres -v ON_ERROR_STOP=1";await sbx.exec(`${psql} -f schema.sql`, { check: true });const count = await sbx.exec(`${psql} -Atc 'select count(*) from users'`, { check: true });console.log("users:", count.stdout.trim());await sbx.exec("pg_dump -h 127.0.0.1 -U postgres -Fc -f /workspace/app.dump postgres", { check: true,});await writeFile("app.dump", await sbx.files.read("/workspace/app.dump"));Pythonfrom withruntime import SandboxBIN = "/usr/lib/postgresql/16/bin"PSQL = "psql -h 127.0.0.1 -U postgres -v ON_ERROR_STOP=1"with Sandbox.create(timeout_seconds=1800) as sbx: sbx.exec("sudo apt-get update -qq && sudo apt-get install -y -qq postgresql", check=True, timeout_ms=600_000) sbx.exec("sudo pg_dropcluster --stop 16 main", check=True) sbx.exec(f"{BIN}/initdb -D /workspace/pgdata -U postgres --auth=trust", check=True) sbx.spawn(f"{BIN}/postgres -D /workspace/pgdata -k /tmp -c listen_addresses=127.0.0.1") sbx.exec("timeout 60 bash -c 'until pg_isready -q -h 127.0.0.1; do sleep 0.5; done'", check=True, timeout_ms=90_000) sbx.files.upload("schema.sql", "/workspace/schema.sql") sbx.exec(f"{PSQL} -f schema.sql", check=True) print(sbx.exec(f"{PSQL} -Atc 'select count(*) from users'", check=True).stdout) sbx.exec("pg_dump -h 127.0.0.1 -U postgres -Fc -f /workspace/app.dump postgres", check=True) sbx.files.download("/workspace/app.dump", "app.dump")spawnkeeps the server running after the call returns. A process started withexecends when its command ends.--auth=trustlets any process in the sandbox connect without a password. Only code you run there, and you through the forward below, can reach127.0.0.1. Nothing on the internet can connect in to a sandbox.-k /tmpputs the Unix socket where the sandbox user may write it.
One seeded database per test
TypeScriptimport { Sandbox } from "withruntime";declare const seeded: Sandbox; // the sandbox above, schema and fixtures loadedconst copies = await seeded.fork({ count: 10 });const results = await Promise.all( copies.map((db, i) => db.exec(`psql -h 127.0.0.1 -U postgres -f tests/case-${i}.sql`, { timeoutMs: 300_000 }), ),);await Promise.all(copies.map((db) => db.stop()));console.log(results.map((r) => r.exitCode));A fork copies files, memory and running processes. Postgres in each copy is therefore the same server, in the middle of its work. It is not a fresh start or a restore. The source is paused while the capture runs, and it runs again when the fork returns. Forks make 1 to 100 copies per call. To start copies later, take a snapshot and create sandboxes from it.
Connect from your laptop or a GUI
Forward the port, then point psql, DBeaver, TablePlus or your app at
localhost:
Pythonimport osimport psycopg # pip install "psycopg[binary]"from withruntime import Sandboxsbx = Sandbox.connect(os.environ["SANDBOX_ID"])with sbx.forward_port(5432, local_port=15432) as forward: with psycopg.connect(f"postgresql://postgres@127.0.0.1:{forward.local_port}/postgres") as conn: print(conn.execute("select version()").fetchone())Terminalruntime sandboxes port-forward <id> 15432:5432psql postgresql://postgres@127.0.0.1:15432/postgresThe forward is a WebSocket through Runtime's API. It uses your key (forward ports) and works without credit. To give a service outside Runtime a connection string instead, a paid account can open a public TCP port (networking).
Keep the data
| You want | Use |
|---|---|
| Come back to the same running database | Pause: files, memory and processes are kept while you have credit, and the next request wakes it |
| Many databases from one prepared state, later | A snapshot, then sandboxes.create({ snapshot }) |
| Data that outlives any sandbox | initdb onto a volume mounted at /data; run sync after writes you must keep |
| A copy on your own machine | pg_dump, then files.read as above |
A sandbox with a volume attached cannot be snapshotted. A fork takes a snapshot. So choose for each database: fast copies, or a disk that outlives the machine.
A newer PostgreSQL, or Postgres in every sandbox
The PostgreSQL project's apt repository supports Ubuntu 24.04. Its script adds
the repository. The -y flag skips its prompt:
Terminalsudo apt-get install -y postgresql-commonsudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -ysudo apt-get install -y postgresql-18 # binaries in /usr/lib/postgresql/18/binTo skip the install in every sandbox, build PostgreSQL into a custom image. Building is free, and an account without credit stores three images free.
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "postgres", recipe: { apt: ["postgresql"], commands: ["pg_dropcluster --stop 16 main"] },});Pythonfrom withruntime import Runtimeruntime = Runtime()runtime.images.build(name="postgres", recipe={"apt": ["postgresql"], "commands": ["pg_dropcluster --stop 16 main"]})A sandbox from the image starts at the initdb step of the first sample.
For Postgres next to an app and a cache, a Compose file is often simpler. See Docker Compose integration tests. For agents that need a database to try migrations against, see a coding agent sandbox.
Sources
- Ubuntu 24.04 postgresql-16 package, from the noble-updates package index at http://archive.ubuntu.com/ubuntu/dists/noble-updates/main/binary-amd64/, read 25 October 2026
- PostgreSQL downloads for Ubuntu, https://www.postgresql.org/download/linux/ubuntu/, read 25 October 2026
- apt.postgresql.org.sh options, https://salsa.debian.org/postgresql/postgresql-common/-/raw/master/pgdg/apt.postgresql.org.sh, read 25 October 2026
Facts on this page were checked on 25 October 2026.