Database Operations
The AISIX Enterprise control plane keeps all its state in one PostgreSQL database, either the bundled PostgreSQL instance or an external database. This page is for the operators of that database. It covers what grows, how much disk to plan for, what the control plane maintains on its own, and what to watch.
Most of the database is configuration, which stays small. A few tables grow with traffic or time, and the control plane deletes their old rows on a schedule. No routine maintenance job is required from you.
What Grows and How It Is Bounded
The control plane deletes old rows in small batches on a schedule, mostly once a day, with the first run when cp-api starts. Deleting an organization also removes its usage records, audit events, and notification delivery records in the background.
| Data | Table | Kept for |
|---|---|---|
| Usage records, behind Request Logs and Usage | dpmgr_usage_events | Each organization's usage retention window: 30 days by default, adjustable from 1 to 365 days. See Data Retention. |
| Audit events | audit_events | audit.retention_days, 730 days by default. 0 keeps them forever. See Audit Log Retention. |
| Notification delivery records | notification_deliveries | 90 days. |
| Budget alert records, which stop an alert from firing twice in one budget period | budget_alert_firings | 90 days after their budget period started. |
| Gateway reports of rejected configuration, and their history | dpmgr_rejected_resources, dpmgr_rejected_resources_audit | 7 days after a gateway last reported the rejection; history for 90 days. |
| Gateway instance records | dp_nodes | About an hour after the gateway instance stops sending heartbeats. |
| Usage report receipts, used to discard a report a gateway sends twice | dpmgr_usage_batches | 24 hours. |
| Dashboard sign-in sessions | auth.console_session | 1 day after they expire. |
| Configuration revisions | kine | Superseded revisions are compacted every few minutes. |
Usage records are the only data whose size follows request volume, so they dominate the database. For usage history longer than an organization's retention window, send usage events to external storage with an observability exporter.
Plan Capacity
Size the database for the usage retention your organizations use, 30 days by default and at most 365. The control plane writes one record per request attempt, so a request that retries or falls back to another target writes more than one. Record size also changes as usage fields and indexes evolve, so use the measured size of your own dpmgr_usage_events table instead of a fixed per-record estimate.
After the table contains a complete retention window under representative traffic, its total relation size is the best baseline. Do not project from net daily growth at steady state, because retention deletion and ingestion can make that value approach zero.
If organizations use roughly the same retention period, scale the baseline in proportion to a planned retention or traffic change. If their retention periods differ substantially, estimate each organization's share from its usage-event volume and retention, then add the shares. When that breakdown is unavailable, planning as if all traffic used the longest configured retention gives a conservative upper bound.
Add headroom for retries, bloat between vacuums, and traffic growth, then add the audit log, the PostgreSQL write-ahead log, and the free space that reclaiming disk space needs. Use the monitoring queries to revise the estimate as traffic or the stored event shape changes.
Routine Maintenance Is Automatic
PostgreSQL autovacuum reclaims the space of deleted rows so new rows can reuse it. Because the control plane deletes old rows every day, the large tables reach a steady size instead of growing without bound.
PostgreSQL's default autovacuum settings wait until a fifth of a table has changed, which is too late for a table with tens of millions of rows. At startup, the control plane sets these table-level parameters on its large tables:
autovacuum_vacuum_scale_factor = 0.02
autovacuum_vacuum_insert_scale_factor = 0.02
autovacuum_analyze_scale_factor = 0.01
Do not change these three parameters by hand. The control plane restores them the next time it starts. Other table-level parameters you add are left as they are. To see which tables carry them, run:
SELECT n.nspname AS schema, c.relname AS table_name, c.reloptions
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.reloptions IS NOT NULL
ORDER BY 1, 2;
Keep autovacuum enabled for the instance (autovacuum = on, the PostgreSQL default) and for these tables. Table-level settings have no effect while autovacuum is off.