Skip to main content
Decision Control Tower stores its own state — registered environments, promotion requests, audit log — in a relational database. Schema management is automated via Flyway: when the application starts it inspects the database, creates the baseline if needed and applies any outstanding migrations before serving traffic.

Supported engines and versions

The reference is PostgreSQL 18; the CI matrix exercises 14 and 18 to cover the supported range. The Tower Sidecar component (see chapter 4) requires its own dedicated PostgreSQL database — do not share schemas between Tower and Sidecar.

Schema requirements

The application user only needs read/write/DDL on its own schema:
  • CONNECT on the database
  • USAGE and CREATE on the public schema
  • The user is expected to be the owner of the database. Flyway requires DDL to create the migration history table on first startup.
If your security policy forbids dynamic DDL by application users, apply the schema manually before first startup using the SQL files under dc-tower-core/src/main/resources/db/migration/ and switch Flyway off via spring.flyway.enabled=false. Note that this requires careful coordination on every release that ships a new migration.

Provisioning steps

The following SQL provisions a fresh database compatible with Tower’s defaults. Run as a PostgreSQL superuser:
Optionally, grant a separate read-only role for monitoring or BI tools (see “Operational access patterns” below). For deployments that must use a non-default database name, override ALETYX_DC_TOWER_DB_URL:
The application uses spring.jpa.hibernate.ddl-auto=validate, which means Hibernate verifies that the runtime entity model matches the schema produced by Flyway. If validation fails, the application fails to start with a clear error in the logs — do not ignore these.

Migration and upgrade considerations

Flyway history table

The first time Tower starts against the database, Flyway creates the table flyway_schema_history in the public schema. Each migration is recorded with its checksum, so subsequent startups apply only newly added migrations.

Migration files shipped with the application

The current image carries the following migrations under db/migration/: The number of files grows over time — consult the image you are deploying for the current set.

Upgrade procedure

  1. Back up the database before any upgrade. Tower migrations are forward-only; rollback in production requires restoring from backup.
  2. Stop the running Tower instance, or scale the Deployment to zero replicas (Kubernetes).
  3. Verify there are no long-running transactions against decision_tower_db from external tools.
  4. Start the new image. Tower applies pending migrations on startup; the application logs each migration as it runs and records it in flyway_schema_history.
  5. Confirm the application reaches the Started AletyxTowerCoreApplication log line and that /actuator/health returns 200 OK before allowing traffic.
If a migration fails partway, Tower fails fast and exits. The schema is left in the partially-migrated state recorded in flyway_schema_history (the failed migration is marked with success = false). Restore from backup, fix the underlying issue (often a schema drift introduced by manual ALTER TABLE outside Flyway), and retry.

Skipping migrations / repairing state

Two operational situations may require a Flyway repair:
  • A migration was edited in place after being applied (checksum mismatch). The fix is to revert the migration to its applied form, or run flyway repair against the database.
  • A migration file was renamed or deleted between releases. Coordinate with Aletyx support before applying — this almost always indicates an unintended downgrade.

Connection pooling

Tower uses HikariCP (Spring Boot default). Pool sizing is automatic but can be tuned via standard Spring properties if needed:
For most installations the defaults are appropriate. Significant query latency or connection-acquisition warnings in the logs indicate either an undersized pool or a database resource issue (CPU, IO, or pg_stat_activity showing long-running transactions).

Operational access patterns

Two access patterns are expected in addition to the application user:
  • Read-only access for diagnostic tools or BI dashboards. Create a dedicated role and grant minimal privileges:
    The ALTER DEFAULT PRIVILEGES FOR ROLE tower ensures that tables created by future Flyway migrations are visible to tower_reader automatically. Without it, each new migration would require a manual GRANT.
  • Backups via pg_dump. Tower’s data is fully relational (no large objects, no binary columns), so a logical dump is safe and round-trips cleanly:
    Frequency depends on your retention policy; at minimum, a daily snapshot is recommended for any environment that holds production approval workflows.

Network connectivity

Tower expects to reach the database over TCP/IP on port 5432 (or whatever port the JDBC URL specifies). For deployments where database and application live in the same Kubernetes cluster, prefer in-cluster DNS (<service>.<namespace>.svc.cluster.local) over external addresses to keep traffic on the cluster’s pod network. TLS to the database is not enabled by default. If your security posture requires it, append the standard PostgreSQL JDBC parameters to the URL:
The application image’s truststore includes the publicly-trusted certificate authorities. For self-signed CAs, you will need to extend the truststore at image build time or via the standard JAVA_TOOL_OPTIONS=-Djavax.net.ssl.trustStore=....

Configuration variables

Example: docker-compose for a self-hosted PostgreSQL alongside Tower

This is suitable for evaluation and small single-host deployments. For production the database should run on a managed service or a dedicated PostgreSQL host, separate from the Tower application host.