kad.dev alpha
kad.dev · docs

Managed Postgres and object storage

Updated Oct 11, 2026

Settings → Storage has one button each: Provision Postgres database sets DATABASE_URL, Provision object storage sets six S3_* variables, and running commits restart so the values reach the app. From an agent: provision_postgres and provision_storage, both idempotent.

What is injected

Backend Variables Notes
Postgres DATABASE_URL a postgresql:// URL; Postgres 18, one database per project
Object storage S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY, S3_REGION, S3_FORCE_PATH_STYLE path-style addressing: switch that option on in your S3 client

Neither reaches a static site: the nginx presets run no server (deploy).

Connection pools and the pause

An app that gets no request for a while is paused and resumes on the next one. The connections it held open do not survive the pause. A pool does not notice: the first statement on a pooled connection fails once with server closed the connection unexpectedly, and the next one works. Tell the pool to test a connection before it hands it out:

Client Setting
SQLAlchemy create_engine(url, pool_pre_ping=True)
psycopg_pool ConnectionPool(url, check=ConnectionPool.check_connection)
Django "CONN_HEALTH_CHECKS": True, needed only when CONN_MAX_AGE is not 0

A connection opened per request is not affected. Nothing in DATABASE_URL can switch the test on, so it is a line of your code.

Console and SQL from an agent

The project page's database console opens read-only every time; write mode is a separate switch, and a destructive statement asks for a typed confirmation.

Agents get two tools on the project's own credentials:

  • query_sql runs one read-only statement (SELECT, WITH, EXPLAIN, SHOW, TABLE, VALUES) in a read-only transaction: at most 500 rows, 5 seconds.
  • execute_sql runs writes and schema changes, up to 25 statements in one transaction, all or nothing. A project can require approval first (Settings → Agents).

The bucket

The object explorer browses by folder and takes drag-and-drop uploads. Agents have list_objects, one folder level at a time, and upload_object, one file from base64 bytes, overwriting an existing key. 100 MiB per file.

An optional disk

Separate from both: Mount path in Settings → Storage, empty means off. Each commit has its own data. Seed previews from served commit copies the served commit's disk into every preview at boot, doubling disk per preview; leave it off for a stateless app.

Restore points

A restore point is a snapshot of the production commit's data, picked from a list, newest first; no arbitrary second.

  • Snapshot now, every plan; snapshot_now from an agent, one per 10 minutes per project. The newest 5 manual points are kept.
  • Daily restore-point ladder is paid plans only, opt-in per project, newest 7 kept.
  • When you promote an older commit, the dialog offers Keep current data or Restore point. The second puts the data back and loses everything written since; it asks for a typed confirm word, keeps a safety copy and offers Undo. rollback_commit has the same modes, keep_data (default) and restore_data.

Limits

  • One database and one bucket per project; no choice of Postgres version, no extension list, no pooling, no replicas.
  • No point-in-time recovery, only discrete restore points.
  • No Redis, no queues.
  • No object delete over MCP.
  • Public alpha: restore points are not a backup strategy. Keep your own.
BUILT SLOWLY · SOLO · EU-HOSTED | BUILD 2a0ff80