Skip to content

Postgres

In production, Vega stores all structured metadata in Postgres. This includes projects, repositories, snapshots, scans, findings, events, users, API keys, usage records, worker heartbeats, and operational state fields.

What goes in Postgres vs S3

Postgres stores: anything that needs to be queried, filtered, or joined — project lists, scan status, finding severity counts, worker state.

S3 stores: large binary or text objects that would be inefficient in a relational database — source code archives, JSON event logs, scan reports, debug bundles.

The Postgres row for a scan or artifact holds the S3 object key; the actual file lives in S3.

AWS context

RDS (Relational Database Service) is AWS's managed database service. Vega uses a Postgres-compatible RDS instance. With RDS, AWS handles backups, patching, and failover — you don't manage the database server.

Aurora Postgres is an AWS-native database engine with Postgres compatibility and better performance. The Terraform database module can be configured for either RDS Postgres or Aurora.

The Terraform module is at infra/terraform/modules/database/main.tf.

Connection configuration

VEGA_PERSISTENCE_BACKEND=postgres
VEGA_DATABASE_URL=postgresql://username:password@hostname:5432/vega

DATABASE_URL (without the VEGA_ prefix) is also accepted, for compatibility with tools that set it automatically.

In AWS, the database URL is stored in Secrets Manager and injected into ECS task definitions. The application never sees the raw credential at deploy time.

Schema

The schema evolves through SQL migration files in app/storage/migrations/. See Migrations for the full list and how to apply them.

app/storage/postgres.py contains a single PostgresStore class with typed methods for every table. It uses psycopg (the Python Postgres driver) directly — no ORM.

Debugging

VEGA_PERSISTENCE_BACKEND=postgres but connecting to JSON: Check that the env var is actually set in the process. Print settings.persistence_backend at startup.

Connection refused: 1. Is Postgres running? (pg_isready -h hostname -p 5432) 2. Is VEGA_DATABASE_URL correct? 3. In AWS: can the ECS task security group reach the RDS security group on port 5432?

Migrations not applied: Run python scripts/run-db-migrations.py (local) or scripts/aws/run-migrations.sh dev (AWS). Check the schema_migrations table to see which migrations have been applied.

Constraint violation errors: These usually mean a migration added a new required column but the application is trying to insert a row without it. Make sure migrations run before deploying new code.

Slow queries: Use EXPLAIN ANALYZE on slow queries. The most common issue is a missing index on foreign key columns. Add indexes in a new migration file.