Skip to content

Database and Redis

PostgreSQL is the primary persistent store for SyncTV. User accounts, rooms, playlists, media metadata, audit data, provider credentials, and most durable application state live in PostgreSQL.

Production deployments should treat PostgreSQL as mandatory infrastructure. Back it up before upgrades, test migrations outside production first, and avoid using ephemeral storage for the database.

Default:

database:
url: "postgresql://synctv:synctv@localhost:5432/synctv"

For production, prefer a secret file:

database:
url_file: "/run/secrets/database_url"

Environment variables:

Terminal window
SYNCTV_DATABASE_URL=postgresql://synctv:password@postgres:5432/synctv
SYNCTV_DATABASE_URL_FILE=/run/secrets/database_url

Instead of a full URL, you can use split fields:

database:
host: "postgres.example.com"
port: 5432
username: "synctv"
password_file: "/run/secrets/database_password"
name: "synctv"

If split fields are used without database.url, SyncTV clears the default URL and builds the connection from the split fields. user is accepted as a YAML alias for username; SYNCTV_DATABASE_USER is accepted as an environment alias for SYNCTV_DATABASE_USERNAME.

FieldDefaultPurpose
database.max_connections20Maximum PostgreSQL pool size
database.min_connections5Minimum idle connections
database.connect_timeout_seconds10Timeout while opening a new connection
database.idle_timeout_seconds600How long idle connections may stay open
database.max_lifetime_seconds1800Maximum lifetime before a connection is recycled

For small single-node deployments, defaults are usually enough. Increase max_connections only after checking PostgreSQL capacity and other application pools that share the same database.

Redis is optional in simple single-node mode but strongly recommended for production. It is required for cluster mode.

Redis backs or improves:

  • Token blacklist and revocation sharing.
  • Rate limit counters.
  • Brute-force protection state.
  • Username, permission, and small business caches.
  • OAuth2 state storage.
  • WebAuthn/passkey challenge storage.
  • MFA session storage.
  • Cache invalidation.
  • Cluster pub/sub, node discovery, health state, and stream catch-up.

If Redis is absent in standalone mode, SyncTV uses in-memory fallbacks where possible. Those fallbacks are lost on restart and cannot be shared across replicas.

Single Redis instance:

redis:
url_file: "/run/secrets/redis_url"
key_prefix: "synctv:"

Environment variables:

Terminal window
SYNCTV_REDIS_URL=redis://redis:6379
SYNCTV_REDIS_URL_FILE=/run/secrets/redis_url
redis:
host: "redis.example.com"
port: 6379
username: ""
password_file: "/run/secrets/redis_password"
database: 0

user is accepted as a YAML alias for username; SYNCTV_REDIS_USER is accepted as an environment alias for SYNCTV_REDIS_USERNAME.

Sentinel mode connects to a Redis Sentinel deployment. After repeated health-check failures, SyncTV queries Sentinel for the current master and performs a best-effort Redis connection rebuild and hot-swap.

This is not a strict failover guarantee: in-flight Redis operations can still fail during the failover window, and cluster coordination that relies on Redis locks and pub/sub can still be unsafe. For that reason, Sentinel mode cannot be used with cluster.enabled=true.

redis:
deployment_mode: "sentinel"
sentinel_master_name: "mymaster"
sentinel_addresses:
- "redis://sentinel-0.redis:26379"
- "redis://sentinel-1.redis:26379"
- "redis://sentinel-2.redis:26379"

For clustered SyncTV, prefer a stable single Redis endpoint, a managed Redis service, or a platform that provides stable connection semantics.

When cluster.enabled=true, Redis must be configured. Cluster mode also requires server.cluster_secret.

cluster:
enabled: true
server:
cluster_secret_file: "/run/secrets/cluster_secret"
redis:
url_file: "/run/secrets/redis_url"

Without Redis, multi-replica coordination cannot safely provide node registry, pub/sub, health monitoring, catch-up, and distributed leader election behavior.

  • PostgreSQL must be backed up before upgrades and migrations.
  • Redis is usually short-lived shared state, but losing it can invalidate OAuth2 state, rate-limit counters, token blacklist data, and cluster coordination state.
  • Use a stable redis.key_prefix when sharing a Redis instance with other systems.
  • Do not expose PostgreSQL or Redis directly to the public internet.