Creating Databases

Provision PostgreSQL databases.

Provision PostgreSQL databases.

List Available Regions

Get the list of available regions for database provisioning:

curl https://api.volcano.dev/databases/regions

Response:

[
  {
    "id": "ap-northeast-1",
    "name": "Asia Pacific (Tokyo)"
  },
  {
    "id": "eu-central-1",
    "name": "Europe (Frankfurt)"
  },
  {
    "id": "us-east-1",
    "name": "US East (N. Virginia)"
  }
]

This is a public endpoint (no authentication required). These are the only values region accepts when you create a database, so read them from here instead of hardcoding a list.

List Available PostgreSQL Versions

Get the list of supported PostgreSQL versions, newest first:

curl https://api.volcano.dev/databases/postgres-versions

Response:

[
  {
    "version": "18",
    "name": "PostgreSQL 18",
    "recommended": true,
    "default": true
  },
  {
    "version": "17",
    "name": "PostgreSQL 17"
  },
  {
    "version": "16",
    "name": "PostgreSQL 16"
  }
]

This is a public endpoint (no authentication required). These are the only values pg_version accepts. The entry marked default, PostgreSQL 18, is the version the dashboard preselects; a create request must still name its version. A database keeps the major version it was created with; to move to a newer one, create a database on that version and migrate your data into it.

In local mode, the list holds one entry: PostgreSQL 16, the version the local server runs. Creating a database on any other version is rejected.

Create a Database

curl -X POST https://api.volcano.dev/projects/PROJECT_ID/databases \
  -H "Authorization: Bearer $PLATFORM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "main_db",
    "region": "us-east-1",
    "pg_version": "18",
    "database_type": "volcano-db-xs"
  }'

Request Body:

  • name (required): Database name. Lowercase letters, digits, and underscores only, up to 64 characters. Uppercase letters are lowercased; hyphens, spaces, and other characters return 400. builder_debug is reserved, and so is volcano in local mode.
  • region (required): Region ID (from /databases/regions)
  • pg_version (required): PostgreSQL major version (from /databases/postgres-versions)
  • database_type (optional): Compute size tier (default: volcano-db-xs)

A pg_version outside that list returns 400 Bad Request:

{
  "error": "unsupported pg_version \"14\": supported versions are 16, 17, 18"
}

An internal failure returns 500 Internal Server Error with a stable message identifying the failed step, for example:

{
  "error": "failed to provision database"
}

Connection details and internal diagnostic messages are omitted from the response.

Response:

{
  "id": "db-uuid",
  "name": "main_db",
  "database_type": "volcano-db-xs",
  "status": "provisioning",
  "region": "us-east-1",
  "pg_version": "18",
  "created_at": "2024-01-01T00:00:00Z"
}

Status progression:

  • provisioning - Being created (5-10 seconds)
  • active - Ready to use
  • restoring - Being restored from a backup; not connectable, and most operations on it return 409
  • failed - Creation failed. This is final: the database never becomes active. It keeps its name and counts toward your plan's database limit until you delete it, so delete it before creating it again.
  • deleting - Being torn down

Database Types

Choose a size based on your workload:

TypeRAMUse Case
volcano-db-xsUp to ~1GBDevelopment, small apps
volcano-db-sUp to ~4GBProduction-ready, light traffic
volcano-db-mUp to ~8GBMedium traffic applications
volcano-db-lUp to ~16GBHigh traffic, larger datasets
volcano-db-xlUp to ~32GBHeavy workloads
volcano-db-2xlUp to ~64GBEnterprise-scale

Automatic scaling: All databases automatically scale to zero when idle (after 3 minutes of inactivity) and scale up on demand within their type's limits.

Update Database Type

Change the compute size of an existing database:

curl -X PATCH https://api.volcano.dev/projects/PROJECT_ID/databases/DATABASE_NAME/type \
  -H "Authorization: Bearer $PLATFORM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "database_type": "volcano-db-s"
  }'

Warning: Changing the database type will briefly interrupt database connections while the compute endpoint is reconfigured.

If Volcano cannot save the type change, it returns 500 Internal Server Error with {"error":"failed to update database type"}. Internal diagnostics are omitted.

Get Database Details

curl https://api.volcano.dev/projects/PROJECT_ID/databases/DATABASE_NAME \
  -H "Authorization: Bearer $PLATFORM_TOKEN"

When status is active, includes connection_string:

{
  "id": "abc-123-456-789",
  "name": "main_db",
  "status": "active",
  "connection_string": "postgresql://volcano_client_11111111-1111-1111-1111-111111111111:vpg_abc123@database.volcano.dev:5432/myapp_main?sslmode=require&application_name=volcano_full_access",
  "region": "us-east-1",
  "pg_version": "18",
  "created_at": "2024-01-01T00:00:00Z"
}

Use this connection_string to connect from your functions or applications. The username and password are Volcano-managed client credentials. The password starts with vpg_; internal credentials are never returned by the API.

Using the Connection String

In functions: set connection_string as a project variable (e.g. DATABASE_URL) — Volcano doesn't set it automatically:

const { Pool } = require('pg');
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});

Direct connection:

psql "postgresql://user:pass@database.volcano.dev:5432/db"

Auth Helpers (Auto-Installed)

When the database is created, Volcano automatically installs:

auth.uid()     -- Get current user ID
auth.email()   -- Get current user email
auth.role()    -- Get current user role

Verify:

psql $CONNECTION_STRING -c "SELECT auth.uid();"

See Auth Helpers for usage.

Multiple Databases

A project can hold several databases, and each one is fully isolated: it gets its own compute, its own storage, and its own connection strings.

Project "my-app"
  ├─ Database: my_app_main       (own compute + storage)
  ├─ Database: my_app_analytics  (own compute + storage)
  └─ Database: my_app_staging    (own compute + storage)

Because nothing is shared between them, a query load spike on one database does not affect the others, and each scales independently within the compute size you pick for it. There is no cross-database querying — a connection to one database cannot read another's tables.

Each database counts against your plan's database limit, and each is billed on its own compute usage. Creating a database with a name already used in the same project returns 409 Conflict; names are compared case-insensitively.

List Databases

curl https://api.volcano.dev/projects/PROJECT_ID/databases \
  -H "Authorization: Bearer $PLATFORM_TOKEN"

Delete a Database

curl -X DELETE https://api.volcano.dev/projects/PROJECT_ID/databases/DATABASE_NAME \
  -H "Authorization: Bearer $PLATFORM_TOKEN"

This permanently deletes the database. Cannot be undone.

If Volcano cannot schedule deletion, it returns 500 Internal Server Error with {"error":"failed to schedule database deletion"}. Internal diagnostics are omitted.

Reset Password

curl -X POST https://api.volcano.dev/projects/PROJECT_ID/databases/DATABASE_NAME/reset-password \
  -H "Authorization: Bearer $PLATFORM_TOKEN"

Response:

{
  "message": "Password reset successfully",
  "role_name": "volcano_client_11111111-1111-1111-1111-111111111111",
  "new_password": "vpg_new_secure_password",
  "connection_string": "postgresql://volcano_client_11111111-1111-1111-1111-111111111111:vpg_new_secure_password@database.volcano.dev:5432/main_db?sslmode=require&application_name=volcano_full_access"
}

Update your functions' DATABASE_URL with the new connection string. The old Volcano password stops opening new connections within a few seconds of the reset; connections already open keep working until they close. The internal owner password is not rotated and is never exposed to clients.

See Also

On this page