Skip to content

Ent controller persistence ​

The Ent edition controller -- the management-plane component that distributes config to a fleet of gateway data-plane instances -- stores its durable state in a PostgreSQL database. This page records what the controller persists and the architecture decision that chose PostgreSQL over the other candidates. It is short because the decision itself is the point; the operator-facing configuration is covered in CP/DP split and Cluster sync.

When to use this ​

  • You operate the Ent controller and need to know what state survives a controller restart (and what does not) before planning restarts or migrations.
  • You are evaluating the persistence choice -- what is stored, and why PostgreSQL over SQLite or etcd.

What the controller stores ​

The controller's durable store holds four categories of state:

  • Config snapshots. Every published config version is stored immutably, with its version number, author, publish time, and the full YAML. The controller serves the current snapshot to data-plane instances over the cluster-sync protocol and retains history for audit and rollback.
  • License state. The Ent edition license, its entitlements, and the fleet-wide consumption counters (active data-plane instances, feature usage against entitlement limits) are persisted so entitlements survive a controller restart.
  • Fleet membership. The set of registered data-plane instances, their last-seen heartbeat, reported version, and health status. The controller uses this to decide which instances receive a config rollout and to surface fleet health in the web console.
  • Federated analytics. Aggregated analytics streamed up from the data-plane instances (see Analytics stream) are persisted in rollup tables for cross-fleet queries and dashboards.

The decision ​

The controller's persistence backend was chosen via an architecture decision record (ADR). The ADR evaluated SQLite, PostgreSQL, and an external object store. SQLite was rejected because the controller is a multi-writer service (config publishes, heartbeat updates, and analytics ingestion can overlap) and SQLite's single-writer model would serialize those paths. The object-store option was rejected because the query patterns (fleet membership lookups, rollup aggregation, snapshot history) are relational and would require a secondary index anyway. PostgreSQL was chosen for its multi-writer concurrency, mature operational tooling, and relational fit for the four state categories.

The store is accessed only by the controller; data-plane instances never touch the database directly. They receive config and report heartbeats over the cluster-sync protocol, and the controller translates those interactions into database rows.

Runnable demo ​

Run this feature against a live gateway: demos/11-enterprise/ (test script: test-14-ent-controller-persistence.sh) in the repository. The demo documents the current limitations alongside what runs today; see its README.