Electric — Deployment
Setup
Postgres configuration
postgresql.conf
wal_level = logical max_replication_slots = 10
Docker Compose
name: 'electric-backend' services: postgres: image: postgres:16-alpine environment: POSTGRES_DB: electric POSTGRES_USER: postgres POSTGRES_PASSWORD: password ports: ['54321:5432'] volumes: ['./postgres.conf:/etc/postgresql/postgresql.conf:ro'] tmpfs: ['/var/lib/postgresql/data', '/tmp'] command: ['postgres', '-c', 'config_file=/etc/postgresql/postgresql.conf']
electric: image: electricsql/electric:latest environment: DATABASE_URL: postgresql://postgres:password@postgres:5432/electric?sslmode=disable ELECTRIC_SECRET: ${ELECTRIC_SECRET} ports: ['3000:3000'] volumes: ['electric_data:/var/lib/electric'] depends_on: ['postgres']
volumes: electric_data:
Electric Cloud
npx @electric-sql/start my-app pnpm claim && pnpm deploy
Core Patterns
Environment variables
Variable Required Description
DATABASE_URL
Yes Direct Postgres connection (not pooler)
ELECTRIC_SECRET
Yes (prod) API authentication secret
ELECTRIC_INSECURE
Dev only Set true to skip secret requirement
ELECTRIC_STORAGE_DIR
No Persistent shape cache directory
ELECTRIC_POOLED_DATABASE_URL
No Pooled connection for non-replication queries
ELECTRIC_DATABASE_USE_IPV6
No Set true for IPv6 Postgres connections
Kubernetes health checks
livenessProbe: httpGet: path: /v1/health port: 3000 readinessProbe: exec: command: ['curl', '-sf', 'http://localhost:3000/v1/health']
Use exec, not httpGet — 202 means "alive but not ready"
Only 200 means fully ready for traffic
Replication slot cleanup
-- When stopping Electric for extended periods: SELECT pg_drop_replication_slot('electric_slot_default');
-- Prevent unbounded WAL growth: ALTER SYSTEM SET max_slot_wal_keep_size = '10GB'; SELECT pg_reload_conf();
Common Mistakes
CRITICAL Not setting wal_level to logical
Wrong:
postgresql.conf (default)
wal_level = replica
Correct:
wal_level = logical max_replication_slots = 10
Electric requires logical replication. The default wal_level = replica does not support it. Requires Postgres restart after change.
Source: packages/sync-service/dev/postgres.conf
CRITICAL Running without ELECTRIC_SECRET in production
Wrong:
docker run electricsql/electric
-e DATABASE_URL=postgres://user:pass@host/db
Correct:
docker run electricsql/electric
-e DATABASE_URL=postgres://user:pass@host/db
-e ELECTRIC_SECRET=my-secret-key
Since v1.x, ELECTRIC_SECRET is required. Without it, Electric refuses to start unless ELECTRIC_INSECURE=true is set (dev only).
Source: packages/sync-service/CHANGELOG.md:832-834
MEDIUM Using ephemeral storage for ELECTRIC_STORAGE_DIR
Wrong:
electric: image: electricsql/electric:latest
No volume — shape cache lost on restart
Correct:
electric: image: electricsql/electric:latest volumes: ['electric_data:/var/lib/electric']
Electric caches shape logs on disk. Ephemeral storage causes full re-sync on every container restart.
Source: website/docs/guides/deployment.md:133-157
MEDIUM Using deprecated ELECTRIC_QUERY_DATABASE_URL
Wrong:
ELECTRIC_QUERY_DATABASE_URL=postgres://user:pass@pooler:6432/db
Correct:
ELECTRIC_POOLED_DATABASE_URL=postgres://user:pass@pooler:6432/db
Renamed from ELECTRIC_QUERY_DATABASE_URL to ELECTRIC_POOLED_DATABASE_URL in v1.3.x. The old name may stop working in future versions.
Source: packages/sync-service/CHANGELOG.md:415
See also: electric-proxy-auth/SKILL.md — Production requires proxy with ELECTRIC_SECRET. See also: electric-postgres-security/SKILL.md — Deployment requires correct Postgres configuration. See also: electric-debugging/SKILL.md — Many sync issues stem from deployment configuration.
Version
Targets Electric sync service v1.x.