Database
Create and manage Postgres databases with ccp db.
Database
Cluster provides managed Postgres databases running in Firecracker microVMs. Each database gets its own isolated VM with a SQL-over-HTTP proxy for secure access.
Create a Database
ccp db create --name my-app-db
# ✓ Created database my-app-db
#
# ID db-c1cf9a9be667
# Host db-c1cf9a9be667.clusterbase.dev
# Token a9db7b185e40...
#
# ✓ Token saved to .cluster/config.jsonIf you run this from a project directory with a .cluster/config.json, the database credentials (DATABASE_URL and DATABASE_TOKEN) are automatically injected as environment variables into your linked function.
List Databases
ccp db list
# • my-app-db ready db-c1cf9a9be667
# db-c1cf9a9be667.clusterbase.devShow Database Details
ccp db info db-c1cf9a9be667
# Database my-app-db
#
# ID db-c1cf9a9be667
# Status ready
# Host db-c1cf9a9be667.clusterbase.dev
# Database default
# User clusterbaseDelete a Database
ccp db destroy db-c1cf9a9be667
# Delete database db-c1cf9a9be667? This will destroy all data. (y/N)Use -y to skip the confirmation prompt.
Interactive SQL Shell
Open an interactive SQL session with ccp db connect:
ccp db connectThis opens a terminal UI with a SQL prompt. Type queries ending with ; to execute them:
╭──────────────────────────────────────────────────╮
│ >_ ccp db connect (db-c1cf9a9be667) │
│ │
│ database: default │
│ host: db-c1cf9a9be667.clusterbase.dev │
╰──────────────────────────────────────────────────╯
› SELECT * FROM users;
id │ name │ email
───┼───────┼──────────────
1 │ Alice │ alice@co.com
(1 row)
43ms
› Enter SQL (end with ;)Meta-commands
| Command | Description |
|---|---|
\dt | List all tables |
\d <table> | Describe a table (columns, types) |
\q | Quit |
Navigation
- Up/Down arrows — cycle through query history
- Ctrl+D or Ctrl+C — exit (clears input if non-empty)
One-Shot SQL
Execute a single SQL statement without opening the interactive shell:
ccp db exec "SELECT count(*) FROM users;"
#
# count
# ─────
# 42
#
# (1 row)
#
# 38msWorks for any SQL — SELECT, INSERT, UPDATE, DELETE:
ccp db exec "INSERT INTO users (name, email) VALUES ('Bob', 'bob@co.com');"
#
# 1 row affected · 45msStatements with RETURNING clauses display the returned rows:
ccp db exec "DELETE FROM users WHERE id = 1 RETURNING *;"Migrations
Run SQL migration files against your database with ccp db migrate. Migrations are tracked in a _ccp_migrations table so they only run once.
Setup
Create a migrations/ directory in your project with numbered .sql files:
migrations/
001_create_users.sql
002_add_posts.sql
003_add_indexes.sqlEach file can contain multiple SQL statements. PL/pgSQL functions with $$ dollar-quoting are fully supported.
Run Migrations
ccp db migrate
# › Running 3 pending migrations...
#
# ✓ 001_create_users.sql 48ms
# ✓ 002_add_posts.sql 37ms
# ✓ 003_add_indexes.sql 42ms
#
# ✓ 3 migrations appliedRunning again is safe — only pending migrations are applied:
ccp db migrate
# ✓ All 3 migrations already appliedCheck Status
See which migrations have been applied without running anything:
ccp db migrate --status
# › Migration status:
#
# ✓ 001_create_users.sql
# ✓ 002_add_posts.sql
# ○ 003_add_indexes.sql
#
# 1 pending migrationOptions
| Flag | Description |
|---|---|
--dir <PATH> | Migrations directory (default: ./migrations) |
--db-id <ID> | Database ID (reads from .cluster/config.json if omitted) |
--token <TOKEN> | Database token (reads from .cluster/config.json if omitted) |
--status | Show migration status without applying |
If you provide --db-id, you must also provide --token (and vice versa).
How It Works
Each migration runs in a database transaction. The migration SQL and the tracking insert are atomic — if the migration fails, nothing is committed. Migrations are applied in filename order, so use a numeric prefix (001_, 002_, etc.) to control the sequence.
Backups
Databases are backed up automatically once per day and backups are retained for 7 days. You can also create manual backups on demand.
Create a Backup
ccp db backup create
# ✓ Backup created
# ID bkp-8f3e2a1c
# Created 2026-04-12 14:22 UTCUse --db-id <ID> to target a database other than the one in your .cluster/config.json.
List Backups
ccp db backup list
# • bkp-8f3e2a1c manual 2026-04-12 14:22 UTC
# • bkp-7d1f9e4b scheduled 2026-04-11 00:00 UTC
# • bkp-6c9a2d7e scheduled 2026-04-10 00:00 UTCls is an alias for list.
Restore from a Backup
ccp db backup restore bkp-8f3e2a1c
# Restore database db-c1cf9a9be667 from bkp-8f3e2a1c? This will overwrite current data. (y/N)Use -y / --yes to skip the confirmation prompt.
Delete a Backup
ccp db backup delete bkp-8f3e2a1crm is an alias for delete.
Querying from Handlers
Access your database from serverless functions using the SQL-over-HTTP proxy:
const res = await fetch(`https://${process.env.DATABASE_ID}.clusterbase.dev/query`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.DATABASE_TOKEN}`,
},
body: JSON.stringify({
sql: "SELECT * FROM users WHERE id = $1",
params: [42],
}),
});
const { rows } = await res.json();Endpoints
| Endpoint | Method | Description |
|---|---|---|
/query | POST | Execute a SELECT query, returns { rows, fields } |
/execute | POST | Execute INSERT/UPDATE/DELETE, returns { rows_affected } |
/transaction | POST | Execute multiple statements atomically |
Request Format
{
"sql": "SELECT * FROM users WHERE id = $1",
"params": [42]
}Parameters use $1, $2, etc. for positional binding.
Transaction Format
{
"statements": [
{ "sql": "INSERT INTO users (name) VALUES ($1)", "params": ["Alice"] },
{ "sql": "INSERT INTO logs (action) VALUES ($1)", "params": ["user_created"] }
]
}Aliases
| Command | Alias |
|---|---|
ccp db list | ccp db ls |
ccp db destroy | ccp db rm |