Skip to Content
TestingManaged Databases

Managed Databases

Enable any app to get a one-click managed Postgres database with automatic environment injection. No manual database setup, no credential management.

Status

Databases are in preview: the REST API and MCP surface are final, but provisioning returns placeholder connection values (host stub-shared-pg-01.local) instead of a live Postgres instance. When managed provisioning goes live, the same calls return real connections. Code written against the injected env vars keeps working unchanged.

Overview

Managed databases are stored in data/app-infra/databases.json with append-only semantics. The password is returned exactly once from the provision call and never stored at rest. The MCP tool automatically publishes DATABASE_URL into the app’s environment via the App Secrets producer API, so the password never reaches the caller.

End-to-End Flow

  1. Operator calls add_app_database(app_id='app-abc123', engine='postgres') via MCP.
  2. The MCP tool verifies app ownership, then POSTs to the platform REST API /api/app-infra/databases with the app details.
  3. The platform provisions the database (in preview: a placeholder connection; once live: a real database on a shared Postgres host) and returns db_id plus password once.
  4. The MCP tool immediately publishes DATABASE_URL into the app’s env via the producer API (Bearer token); the caller never sees the password.
  5. The MCP tool appends db_id to App.db_refs and returns {db_id, status, env_keys, env_published, session_token, next}.
  6. On next deploy_app call, the app VM receives DATABASE_URL in /etc/openfactory/app.env automatically; the app connects without any manual credential setup.

MCP Tools

ToolPurposeExample Call
add_app_database

Provision a managed Postgres database for an app and automatically publish DATABASE_URL into the app’s environment.

add_app_database(app_id=‘app-12345678’, engine=‘postgres’)
list_app_databases

List all databases provisioned for an app (metadata only, no passwords).

list_app_databases(app_id=‘app-12345678’)

add_app_database

Provision a managed Postgres database for an app and automatically publish DATABASE_URL into the app’s environment.

Example Call:

add_app_database(app_id='app-12345678', engine='postgres')

Example Response (when env_published=true):

{ "db_id": "db-a1b2c3d4e5f6", "status": "stub", "engine": "postgres", "env_keys": ["DATABASE_URL"], "env_published": true, "session_token": "user@example.com", "next": "deploy_app(app_id='app-12345678', vm_name=...). DATABASE_URL is already in the app's env and will be injected on the next deploy." }

Example Response (when env_published=false):

{ "db_id": "db-a1b2c3d4e5f6", "status": "stub", "engine": "postgres", "env_keys": [], "env_published": false, "connection_url": "postgres://app_myapp:password123@stub-shared-pg-01.local:5432/app_myapp", "publish_skipped_reason": "OPENFACTORY_DB_PRODUCER_TOKEN is not configured", "session_token": "user@example.com", "next": "set_app_env(app_id='app-12345678', set={'DATABASE_URL': <connection_url>}) then deploy_app(...)" }

list_app_databases

List all databases provisioned for an app (metadata only, no passwords).

Example Call:

list_app_databases(app_id='app-12345678')

Example Response:

{ "databases": [ { "db_id": "db-a1b2c3d4e5f6", "app_id": "app-12345678", "engine": "postgres", "shape": "shared-tenant", "shared_host": "stub-shared-pg-01.local", "database": "app_myapp", "username": "app_myapp", "host": "stub-shared-pg-01.local", "port": 5432, "status": "stub", "notes": "STUB MODE: no real Postgres provisioned.", "created_at": "2026-06-26T01:52:00Z" } ], "session_token": "user@example.com" }

MCP Response Fields:

  • session_token: Appended by the MCP tool wrapper (not present in raw REST responses)
  • All other fields come directly from the REST API

REST API

MethodPathPurposeAuth
POST/api/app-infra/databasesProvision a new managed Postgres database for an app. Returns the connection details (host, port, database, username, password, url) exactly once; password never stored.JWT (authenticated user; requests are scoped to apps you own)
GET/api/app-infra/databases/{db_id}Fetch metadata for a specific database (no password). Returns database configuration, host, port, status, and creation timestamp.JWT (authenticated user)
GET/api/app-infra/databases?app_id={app_id}List all databases for an app with optional filtering by app_id. Returns metadata only (no passwords).JWT (authenticated user)

Provision Endpoint

Request (POST /api/app-infra/databases):

{ "app_id": "app-12345678", "owner_user_id": "user@example.com", "slug": "my-app", "engine": "postgres" }

Response (201):

{ "db_id": "db-a1b2c3d4e5f6", "status": "stub", "connection": { "host": "stub-shared-pg-01.local", "port": 5432, "database": "app_myapp", "username": "app_myapp", "password": "actual_password_here", "url": "postgres://app_myapp:actual_password_here@stub-shared-pg-01.local:5432/app_myapp" } }

The password is returned exactly once and must be published to the app’s environment immediately. Subsequent GET requests never return the password.

Get Database Metadata

Response (GET /api/app-infra/databases/{db_id}):

{ "db_id": "db-a1b2c3d4e5f6", "app_id": "app-12345678", "engine": "postgres", "shape": "shared-tenant", "shared_host": "stub-shared-pg-01.local", "database": "app_myapp", "username": "app_myapp", "host": "stub-shared-pg-01.local", "port": 5432, "status": "stub", "notes": "STUB MODE: no real Postgres provisioned.", "created_at": "2026-06-26T01:52:00Z" }

List Databases

Response (GET /api/app-infra/databases?app_id=app-12345678):

{ "databases": [ { "db_id": "db-a1b2c3d4e5f6", "app_id": "app-12345678", "engine": "postgres", "shape": "shared-tenant", "shared_host": "stub-shared-pg-01.local", "database": "app_myapp", "username": "app_myapp", "host": "stub-shared-pg-01.local", "port": 5432, "status": "stub", "notes": "STUB MODE: no real Postgres provisioned.", "created_at": "2026-06-26T01:52:00Z" } ] }
Last updated on