PostgreSQL
Use PostgreSQL instead of SQLite when you need more write concurrency or must use existing database infrastructure.
Connection String
Set a PostgreSQL connection string with a CLI flag or environment variable:
# CLI flag
./windshift --postgres-connection-string "postgres://user:password@localhost:5432/windshift?sslmode=disable"
# Short flag
./windshift --pg-conn "postgres://user:password@localhost:5432/windshift?sslmode=disable"
# Environment variable
export POSTGRES_CONNECTION_STRING="postgres://user:password@localhost:5432/windshift?sslmode=disable"
./windshiftWhen you set a PostgreSQL connection string, Windshift uses PostgreSQL and ignores the --db flag.
Connection Pool
Windshift limits the PostgreSQL pool size. This prevents a busy instance or agent traffic burst from exhausting database connections. Windshift sizes the pool from MAX_READ_CONNS:
| Setting | Default | Source |
|---|---|---|
| Max open connections | 30 | MAX_READ_CONNS |
| Max idle connections | 15 | half of MAX_READ_CONNS |
Windshift recycles idle connections after their lifetime and idle timeout. To raise the limit, increase MAX_READ_CONNS (--max-read-conns). Keep it below the PostgreSQL server's max_connections. Reserve connections for other clients, runners, and sidecars.
Per-user concurrency
MAX_USER_CONCURRENCY (default 16) limits the simultaneous /api requests from one authenticated user or agent. This prevents one heavy client from monopolizing the pool. Set it to 0 to remove the limit.
Go's database/sql package manages the pool.
Docker Compose Setup
services:
windshift:
image: ghcr.io/windshiftapp/windshift:latest
restart: unless-stopped
ports:
- "8080:8080"
tmpfs:
- /tmp:exec,size=64M
environment:
- BASE_URL=https://windshift.example.com
- SSO_SECRET=${SSO_SECRET}
- POSTGRES_CONNECTION_STRING=postgres://windshift:${POSTGRES_PASSWORD}@postgres:5432/windshift?sslmode=disable
- ATTACHMENT_PATH=/data/attachments
volumes:
- windshift-data:/data
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:18
restart: unless-stopped
environment:
- POSTGRES_USER=windshift
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=windshift
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U windshift"]
interval: 5s
timeout: 5s
retries: 5
volumes:
windshift-data:
postgres-data:PostgreSQL major upgrades
The Compose examples use PostgreSQL 18. Do not change a PostgreSQL image to a different major version when it uses an existing data volume. Use pg_upgrade or a dump and restore. PostgreSQL will not start a data directory created by another major version.
Schema Management
Windshift manages database schemas automatically. At startup, it runs embedded migration files for items, users, tests, workflows, portals, notifications, and permissions. It converts SQL placeholders between SQLite (?) and PostgreSQL ($1, $2, and similar) syntax.
Do not run manual schema setup or migration commands.
SSL/TLS
For a production PostgreSQL connection, set sslmode in the connection string:
# Require SSL
--pg-conn "postgres://user:pass@db.example.com:5432/windshift?sslmode=require"
# Verify server certificate
--pg-conn "postgres://user:pass@db.example.com:5432/windshift?sslmode=verify-full&sslrootcert=/path/to/ca.pem"The split-variable configuration supports the same TLS modes with POSTGRES_SSLMODE:
DB_TYPE=postgres
POSTGRES_HOST=db.example.com
POSTGRES_USER=windshift
POSTGRES_PASSWORD=secret
POSTGRES_DB=windshift
POSTGRES_SSLMODE=requirePOSTGRES_SSLMODE defaults to disable. This setting fits the bundled postgres container on the same Docker network. For a remote or managed database, use require, verify-ca, or verify-full. Accepted modes are disable, allow, prefer, require, verify-ca, and verify-full.
Backups
Use standard PostgreSQL backup tools:
# Logical backup
pg_dump -U windshift windshift > backup.sql
# Compressed backup
pg_dump -U windshift -Fc windshift > backup.dump
# Restore
pg_restore -U windshift -d windshift backup.dumpMigrating from SQLite
To migrate an existing SQLite database to PostgreSQL:
- Set up a new PostgreSQL database.
- Start Windshift with the PostgreSQL connection string. Windshift creates all tables.
- Export the SQLite data. Import it into PostgreSQL with standard tools.
There is no built-in migration command at this time.