Clusters
A cluster is one logical PostgreSQL database — a primary node plus zero or more async read replicas — managed as a single resource. Operations that affect every node go here; per-node operations live in Nodes.
Create
POST /database/cluster/create
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "app-prod",
"image_id": 1,
"instance_type": "m1a.xlarge",
"subnet_id": 1,
"zone_id": 1,
"project_id": 1,
"allocate_public_ipv4": false,
"is_multi_az": false,
"security_group_ids": [12]
}Required: name, image_id, instance_type, subnet_id, zone_id, project_id, allocate_public_ipv4.
Optional: is_multi_az (provisions two standbys), security_group_ids, ssh_pubkey, network_interfaces.
The response returns:
| Field | Notes |
|---|---|
id | Cluster ID — pin this in your config |
name | Echoed back |
hostname | DNS name clients connect to |
nodes[] | One element today (the primary) |
postgres_password | Shown once. Save it immediately |
The default database user is postgres.
List
GET /database/list?zone_id=1
Authorization: Bearer <token>Omit zone_id to list across every zone. The response returns clusters with their hostname, id, name, and nodes — never the postgres password.
Restart
POST /database/cluster/restart
Authorization: Bearer <token>
Content-Type: application/json
{ "cluster_id": <id> }Rolls every node — replicas first, then the primary with a failover. Typical downtime for the primary is a few seconds during the failover.
Terminate
POST /database/cluster/terminate
Authorization: Bearer <token>
Content-Type: application/json
{ "cluster_id": <id> }Irreversible. Take a backup first if you might need the data. Terminate removes every node, releases storage, and drops the DNS record for the hostname.
Rotate the admin password
POST /database/resetpassword
Authorization: Bearer <token>
Content-Type: application/json
{ "cluster_id": <id> }Response includes db_password and invalidates the old one immediately. To roll without an outage:
revealthe current password from Secrets and verify your app reads it that way.- Call
resetpassword. - Update the secret to the new value (
exc secret version add). - Restart / signal your app so it re-fetches.
Apps that cache the password forever will start failing the moment step 2 lands — plan accordingly.
Hostname
The hostname returned at create time is stable for the life of the cluster — it doesn’t change across restarts, password rotations, or node-add operations. Failover redirects automatically. Apps should resolve the hostname and reconnect on failure, not cache the underlying IP.
Required permissions
| Action | Permission |
|---|---|
| Create | database:cluster:create |
| List | database:cluster:list |
| Restart | database:cluster:restart |
| Terminate | database:cluster:terminate |
| Reset password | database:cluster:resetpassword |
Resource scoping: exc:database:cluster/<id>. See the
Policies guide.