Skip to content

Production Configuration Guide

Required Environment Variables

Variable Description Example
DATABASE_URL PostgreSQL connection string postgresql+asyncpg://user:pass@host:5432/zkp_identity
REDIS_URL Redis connection string redis://redis:6379/0
JWT_SECRET_KEY JWT signing key (min 32 chars) <random 64-char string>
ENCRYPTION_KEY AES-256-GCM key (64 hex chars) <random 64 hex chars>
ISSUER_PRIVATE_KEY_HEX Ed25519 signing key (64 hex chars) <random 64 hex chars>
DEBUG Must be false in production false
DOCS_ENABLED Set true only if API docs needed false
FRONTEND_URL Frontend origin for CORS https://app.zkprova.com
CORS_ORIGINS Comma-separated allowed origins ["https://app.zkprova.com"]
API_BASE_URL Public API base URL https://api.zkprova.com/api/v1

Optional

Variable Default Description
SENTRY_DSN (empty) Sentry error tracking DSN
SENTRY_ENVIRONMENT development Sentry environment tag
SENTRY_TRACES_SAMPLE_RATE 0.1 Sentry performance sampling (0.0–1.0)
EMAIL_BACKEND console smtp, sendgrid, or ses for production
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASSWORD Required if EMAIL_BACKEND=smtp
SENDGRID_API_KEY Required if EMAIL_BACKEND=sendgrid
DID_WEB_DOMAIN (empty) Domain for did:web identifiers
METRICS_ENABLED true Expose /metrics for Prometheus
WORKERS 2 Uvicorn worker count (Docker CMD)
PORT 8000 Server port

Database Pool Sizing

Concurrency DB_POOL_SIZE DB_MAX_OVERFLOW Notes
Low (<100 rps) 10 10 Dev/staging
Medium (100–500 rps) 20 20 Default production
High (500+ rps) 30–50 30 Ensure RDS max_connections supports it

Additional pool settings: - DB_POOL_TIMEOUT=30 — seconds to wait for a connection from the pool - DB_POOL_RECYCLE=3600 — recycle connections every hour (avoids stale connections behind load balancers)

Uvicorn Worker Count

Rule of thumb: 2 * CPU_CORES + 1

vCPUs Workers
1 2
2 4
4 8

Set via the WORKERS environment variable in Docker.

Redis Configuration

  • Use Redis 7+ with TLS in production
  • Connection string: rediss://user:password@host:6379/0 (note rediss:// for TLS)
  • Used for: rate limiting (slowapi), session caching
  • Recommended: ElastiCache with automatic failover

Sentry Setup

  1. Create a Sentry project (Python / FastAPI)
  2. Set SENTRY_DSN to the project DSN
  3. Set SENTRY_ENVIRONMENT=production
  4. Set SENTRY_TRACES_SAMPLE_RATE=0.05 (5% in production to control cost)
  5. PII sending is disabled by default (send_default_pii=False)

Health Checks

Endpoint Purpose Use
GET /health/live Liveness probe K8s livenessProbe
GET /health/ready Readiness probe (checks DB + Redis) K8s readinessProbe
GET /health Legacy simple health check Load balancer

Backup Strategy

  • RDS: Enable automated backups with 7-day retention
  • Point-in-time recovery: Enabled by default with RDS
  • Manual snapshots: Before major migrations
  • Cross-region: Consider cross-region read replicas for DR

Monitoring Checklist

  • High error rate: 5xx responses > 1% over 5 minutes
  • High latency: p99 response time > 2s
  • DB pool exhaustion: pool wait time > 10s
  • Circuit breaker open: email or push notification circuit open
  • Rate limiting: high rate of 429 responses
  • Disk usage: > 80% on any volume
  • Memory usage: > 85% container memory

Grafana Dashboards

  • Request rate, latency, and error rate by endpoint
  • Database connection pool utilization
  • Redis hit/miss ratio
  • Active users and credential issuance rate

Security Checklist

  • [ ] DEBUG=false
  • [ ] DOCS_ENABLED=false (or restrict via network policy)
  • [ ] Non-dev JWT secret and encryption key
  • [ ] CORS origins restricted to production domains
  • [ ] HTTPS termination at load balancer / ingress
  • [ ] Container runs as non-root user
  • [ ] Request body size limit enforced (1 MB default)
  • [ ] Security headers middleware active (CSP, HSTS, X-Frame-Options)
  • [ ] Rate limiting configured appropriately
  • [ ] Sentry configured with send_default_pii=False