External Database
An AISIX Cloud control plane installed with Helm can use the chart's bundled PostgreSQL instance or an external PostgreSQL database managed by your DBA team. The external database connection role needs specific database privileges, but not SUPERUSER. Other database engines are not supported.
The online and offline Docker Compose packages do not support an external database. Their Compose files set the control-plane services' database URLs to the bundled postgres service and do not expose overrides in .env. Use Helm when the control plane must connect to an external PostgreSQL database.
The control-plane services share one database:
cp-api: Control-plane API server. It runs the schema migration on startup.dp-manager: Data-plane manager. It connects to the same database but does not run the control-plane application migration. Its embedded Kine backend manages its own storage schema. On a fresh database,dp-managerretries missing application-schema errors for up to about two minutes whilecp-apicompletes the migration.- Dashboard: Control-plane user interface. It stores authentication data in the same database.
PostgreSQL Requirements
- PostgreSQL 14 or later.
- One empty database owned by the role the control plane connects as.
- One login role with
CREATEROLEandBYPASSRLS, but notSUPERUSER. - No PostgreSQL extensions. UUIDs use the built-in
gen_random_uuid().
Why the Control Plane Needs These Privileges
On its first start, cp-api prepares the database schema and creates an internal low-privilege role. The connection role needs enough privilege for that bootstrap work and for shared control-plane operations.
Each privilege has a specific purpose:
- Database ownership lets
cp-apicreate thepublicandauthschemas, tables, indexes, functions, and Row-Level Security policies. Under default PostgreSQL privileges, the database owner can create objects inpublic, so a standard cluster needs no separate schema grant. CREATEROLEletscp-apicreate and configurecp_api_app, the internal role used for tenant-scoped queries with Row-Level Security. You do not create this role yourself.BYPASSRLSlets shared control-plane operations read rows across organizations when required. These paths include caller-token authentication, billing webhooks, the background budget aggregator, anddp-manageroperations.
Tenant-scoped requests still switch to cp_api_app, which has neither SUPERUSER nor BYPASSRLS. The control-plane connection role therefore needs specific PostgreSQL capabilities, but not superuser privileges.
Create the Database and Role
Run this once as a database administrator. Use an account that can create roles, create databases, and grant BYPASSRLS. The control-plane connection role itself does not need to be a superuser.
-- 1) A dedicated login role for the control plane. Not a superuser.
CREATE ROLE aisix LOGIN PASSWORD 'change-me-to-a-strong-password'
NOSUPERUSER CREATEROLE BYPASSRLS;
-- 2) A dedicated database owned by that role.
CREATE DATABASE aisix_cloud OWNER aisix;
Choose your own role name, password, and database name. Ownership is what lets aisix create objects in public and add the auth schema on first boot.
Use a URL-safe password because the password is embedded in a PostgreSQL connection URL. Characters such as +, /, and = can break the DSN unless they are percent-encoded. Generate a URL-safe value instead, for example with openssl rand -hex 24. See On-Premises Installation.
If your DBA has hardened the public schema, for example by revoking the default CREATE privilege, also grant schema access explicitly while connected to the new database:
\c aisix_cloud
GRANT USAGE, CREATE ON SCHEMA public TO aisix;
Do not pre-create the cp_api_app role. The control plane creates and configures it during migration and asserts its attributes. Pre-creating it, especially with different attributes, can make the migration fail its safety checks.
Connect the Control Plane to the Database
With Helm, set the externalDatabase.* values (and postgresql.builtin=false) as described in On-Premises Configuration. The chart builds the connection URLs for the control-plane services from those values.
Set sslmode=require (or stricter, such as verify-full) whenever the database is reached over a network you do not fully control.
What the Control Plane Creates
On the first successful start, cp-api builds the full schema in the database you provisioned. On later starts, it applies pending migrations and skips one-time migrations that have already completed:
- the
publicschema for control-plane tables, such as organizations, environments, models, caller API keys, and budgets, owned by your role; - the
authschema for authentication tables, such as users and sessions; - the
cp_api_approle, withNOSUPERUSER NOBYPASSRLS NOINHERIT NOLOGIN, granted only CRUD on control-plane tables and read/write on a few non-secret identity columns; - Row-Level Security policies that scope each tenant table to a single organization.
The connection role is automatically made a member of cp_api_app so it can switch to that role per request. You do not grant this yourself.
Database Privilege Checklist
Use this checklist when reviewing the database role with your DBA team:
| Requirement | Purpose |
|---|---|
LOGIN | Allows control-plane services to connect as this role. |
| Database ownership | Allows cp-api to create and alter schemas, tables, indexes, functions, and RLS policies. |
CREATEROLE | Allows cp-api to create and manage the internal cp_api_app role. |
BYPASSRLS | Allows cross-organization control-plane paths and dp-manager to read the rows they need on the shared connection. |
Not SUPERUSER | Keeps the role below PostgreSQL superuser privilege. |
Verify the Database Setup
After the control plane starts, connect as an administrator and confirm the bootstrap looks right.
The internal role exists and is correctly de-privileged:
SELECT rolname, rolsuper, rolbypassrls, rolcanlogin
FROM pg_roles WHERE rolname = 'cp_api_app';
-- expect: cp_api_app | f | f | f
Both schemas were created:
SELECT nspname FROM pg_namespace WHERE nspname IN ('public', 'auth');
-- expect: two rows
Troubleshoot Startup Errors
Use the startup error message to find the missing database capability.
cp-api database role must be SUPERUSER or have BYPASSRLS ...
The connection role is missing BYPASSRLS. Grant it as a database administrator:
ALTER ROLE aisix BYPASSRLS;
permission denied for schema public
The role cannot create objects in the public schema. Confirm database ownership. If the schema is locked down, grant schema access explicitly:
\c aisix_cloud
GRANT USAGE, CREATE ON SCHEMA public TO aisix;
permission denied to create role
The connection role is missing CREATEROLE. Grant it as a database administrator:
ALTER ROLE aisix CREATEROLE;
permission denied to set role "cp_api_app"
The migration that grants cp_api_app membership likely did not finish. Check the cp-api startup logs for an earlier migration error.
Next Steps
After the database and role are ready, return to On-Premises Installation and configure the control plane to use the external database.
For the full set of Helm values, see On-Premises Configuration.