Datastore consolidation (ADR-014 step 5)
Source of truth:
docs/runbooks/datastore-consolidation.md(synced at build time — edit the original, not this copy). Identity and every product use onesuite-postgresand onesuite-redis:
| Consumer | PostgreSQL | Redis |
|---|---|---|
| Identity | suite-postgres/veltro_identity (four roles, three DSNs; the importer role has no DSN) |
none |
| VectorFlow | suite-postgres/vectorflow |
redis://suite-redis:6379/0 |
| Sigmatic | suite-postgres/sigmatic (through sigmatic-pgbouncer in the repo compose) |
cache /1, queue /2 |
| Warden | suite-postgres/warden |
redis://suite-redis:6379/3 |
Product hosts and Redis indices are compose literals. The identity DSNs are the only stack environment values that name the host:
VELTRO_IDENTITY_MIGRATION_DATABASE_URL=postgresql://veltro_identity_owner:***@suite-postgres:5432/veltro_identityVELTRO_IDENTITY_RUNTIME_DATABASE_URL=postgresql://veltro_identity_runtime:***@suite-postgres:5432/veltro_identityVELTRO_IDENTITY_RECOVERY_DATABASE_URL=postgresql://veltro_identity_recovery:***@suite-postgres:5432/veltro_identityscripts/validate_identity_credentials.py (run by make up, veltro install and veltro doctor) refuses a migration or runtime DSN whose host isn’t suite-postgres.
What happened
Section titled “What happened”Suite 0.13 added the shared stores beside the eight per-product ones, then switched every consumer to them. The data moved through a protected, fenced migration that release-suite.yml dispatched as one-shots on the deployed stack (#1067).
The homelab migrated on 2026-09-27 (run 36309493050) and switched with suite 0.13.8 (komodo/veltro#52, komodo/resources#232). All four databases and all four Redis indices verified.
The per-product stores, their legacy-datastores profile and the migration one-shots were retired the same day without a soak, after full database backups. The compose files no longer define any of them.
An install still on the per-product stores
Section titled “An install still on the per-product stores”This release can’t move it. Upgrade to suite 0.13.9 first and follow that release’s copy of this runbook, then upgrade from there. Backups taken on the per-product layout restore only with the release that took them (backup-restore.md).
After upgrading
Section titled “After upgrading”docker compose up leaves the old datastore containers running as orphans. Remove them once with --remove-orphans (for example docker compose --env-file versions.env --env-file .env --profile core up -d --remove-orphans with your usual profiles). That removes containers only.
The old named volumes stay on disk, and nothing in Veltro deletes them. Once you’ve checked a backup of the shared stores and no longer need the old data, remove them with docker volume rm. The repo compose named them veltro-veltro-identity-pgdata, veltro-vf-pgdata, veltro-vf-redisdata, veltro-chad-pgdata, veltro-chad-redis-data, veltro-chad-redis-queue-data and veltro-warden-pgdata. Its warden-redis had no volume. The migration also left <project>_datastore-evidence, which is veltro_datastore-evidence when the Compose project is veltro. Hand-maintained stacks differ: the homelab Komodo stack named identity’s volume veltro-identity-pgdata and gave Warden’s Redis veltro-warden-redis-data. Check a stack’s own compose file before deleting anything.
Sizing the shared stores
Section titled “Sizing the shared stores”PostgreSQL connections. SUITE_POSTGRES_MAX_CONNECTIONS (default 250) has to cover every pool that reaches the server: Sigmatic through sigmatic-pgbouncer (PGBOUNCER_DEFAULT_POOL_SIZE, 25), or without the pooler each Sigmatic process’s DATABASE_POOL_SIZE plus DATABASE_MAX_OVERFLOW; VectorFlow’s Prisma pool; Warden’s backend and worker pools; identity; the one-shot migrations; and superuser headroom. Without the pooler, Sigmatic’s four API workers, two ingest workers and two worker replicas each keep their own pool; the homelab was sized at 400 for that. Check the busiest SELECT count(*) FROM pg_stat_activity before lowering it.
Redis memory. suite-redis runs noeviction, so at maxmemory every product’s writes fail, not just one. Keep SUITE_REDIS_MAXMEMORY (default 4 GB) above used_memory_peak from INFO memory, with room for the Sigmatic queue to back up. Sigmatic’s cache relies on bounded TTLs and a bounded dead-letter stream (sigmatic#610) because the shared store never evicts.