Setting Up High Availability for Authentik with PostgreSQL, Redis, and Dramatiq

To achieve high availability for Authentik, deploy stateless server and worker instances behind a load balancer while running PostgreSQL with streaming replication, Redis with Sentinel clustering, and Dramatiq backed by PostgreSQL for durable task queues.

Authentik is architected as a stateless Django application where all session state, configuration, and identity data persist in PostgreSQL. This design simplifies horizontal scaling and eliminates single points of failure at the application layer. Setting up high availability for Authentik with PostgreSQL, Redis, and Dramatiq requires configuring each infrastructure component for redundancy while maintaining the stateless nature of the application servers.

Stateless Server and Worker Architecture

The authentik server and worker processes in goauthentik/authentik are completely stateless. Each instance reads from and writes to the central PostgreSQL database, meaning no local session data persists on individual containers or pods.

This architecture allows you to run multiple instances in parallel without coordination between nodes. If any instance crashes, remaining instances continue serving authentication requests without interruption. Horizontal scaling becomes a matter of increasing replica counts rather than reconfiguring the application.

According to the high-availability documentation, you can safely scale the server deployment to three or more replicas and the worker deployment to two or more replicas to handle background task processing.

PostgreSQL High Availability Configuration

Authentik stores all persistent data in PostgreSQL, making the database layer the most critical component for HA. The repository documentation outlines several strategies for PostgreSQL redundancy.

Primary-Replica Streaming Replication

Configure primary-replica streaming replication to create read-only replicas that offload query traffic from the primary instance. This reduces load on the write-primary while providing hot standby capacity for failover scenarios.

Connection Pooling

Deploy a connection pooler such as PgBouncer or Pgpool between Authentik and PostgreSQL. As documented in website/docs/install-config/configuration/configuration.mdx, poolers prevent "too many connections" errors when scaling Authentik to many instances, since each Django process typically maintains multiple database connections.

Automated Failover

Implement automatic failover and promotion using Patroni, Stolon, or cloud-provider managed PostgreSQL services. These solutions monitor the primary database and elect a new primary from replicas if the original fails, ensuring continuous availability without manual intervention.

Redis Clustering for Session Storage

While PostgreSQL stores core data, Authentik uses Redis for caching computed values and temporary session storage. To prevent the cache layer from becoming a single point of failure, deploy Redis in high-availability mode.

Deployment Patterns

The Authentik configuration supports three Redis deployment models:

  • Standalone Redis – Suitable for development or small deployments without HA requirements
  • Redis Sentinel – Provides automatic master election and failover with minimal configuration overhead
  • Redis Cluster – Offers sharding and horizontal scaling for large-scale deployments with massive cache requirements

Configure the connection using the AUTHENTIK_REDIS__HOST environment variable. The configuration.mdx documentation details additional TLS settings and connection parameters required for secure cluster communication.

Dramatiq Task Queue Configuration

Background jobs in Authentik—including user sync tasks, email delivery, and provisioning operations—execute through Dramatiq, a distributed task processing library. The project uses django-dramatiq-postgres to store the task queue directly in PostgreSQL rather than relying on external message brokers like RabbitMQ or Redis.

PostgreSQL-Backed Broker

The broker implementation in [packages/django-dramatiq-postgres/django_dramatiq_postgres/broker.py](https://github.com/goauthentik/authentik/tree/main/packages/django-dramatiq-postgres/django_dramatiq_postgres) uses PostgresBroker to read from a dedicated database table. It leverages PostgreSQL advisory locks for safe concurrent consumption across multiple worker instances.

Connection Considerations

The Dramatiq broker requires a direct database connection rather than a pooled connection when using PgBouncer. This distinction matters because the broker relies on PostgreSQL's LISTEN/NOTIFY functionality, which connection poolers typically do not support properly. Configure a separate database URL for the broker to bypass the pooler while allowing the main application to use connection pooling.

Task registration occurs in [authentik/tasks/__init__.py](https://github.com/goauthentik/authentik/tree/main/authentik/tasks), where background operations are decorated for Dramatiq processing.

Deployment Examples

Docker Compose for Small-Scale HA

For development environments or small production deployments, extend the standard Docker Compose configuration to support multiple replicas:

version: "3.8"
services:
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    ports: ["6379:6379"]
    # Replace with Redis Sentinel configuration for true HA

  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: authentik
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: authentik
    volumes: ["pgdata:/var/lib/postgresql/data"]
    # Add standby containers for streaming replication

  server:
    image: goauthentik/server:2024.12
    restart: unless-stopped
    depends_on: [postgres, redis]
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgres
    ports: ["9000:9000"]

  worker:
    image: goauthentik/server:2024.12
    command: ["ak", "worker"]
    restart: unless-stopped
    depends_on: [postgres, redis]
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgres

volumes:
  pgdata:

Scale horizontally using docker compose up -d --scale server=3 --scale worker=2. All instances share the same PostgreSQL database and Redis cache, providing redundancy without data consistency concerns.

Kubernetes for Production HA

For production environments, use the official Helm charts with replica configurations:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: authentik-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: authentik
  template:
    metadata:
      labels:
        app: authentik
    spec:
      containers:
      - name: server
        image: goauthentik/server:2024.12
        env:
        - name: AUTHENTIK_REDIS__HOST
          value: "redis-master.authentik.svc.cluster.local"
        - name: AUTHENTIK_POSTGRESQL__HOST
          value: "postgres-primary.authentik.svc.cluster.local"
        ports:
        - containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: authentik-worker
spec:
  replicas: 2
  selector:
    matchLabels:
      app: authentik-worker
  template:
    metadata:
      labels:
        app: authentik-worker
    spec:
      containers:
      - name: worker
        image: goauthentik/server:2024.12
        command: ["ak", "worker"]
        env:
        - name: AUTHENTIK_REDIS__HOST
          value: "redis-master.authentik.svc.cluster.local"
        - name: AUTHENTIK_POSTGRESQL__HOST
          value: "postgres-primary.authentik.svc.cluster.local"

Deploy PostgreSQL using the Bitnami PostgreSQL Helm chart with architecture: replication enabled. Configure Redis using the Redis Helm chart with sentinel.enabled: true. Place a LoadBalancer or Ingress controller in front of the server pods to distribute traffic.

Monitoring and Health Checks

Implement comprehensive health monitoring to detect failures and trigger automated failover.

Application Health: Authentik exposes /api/v3/system/status/ for load balancer health checks. Configure your load balancer to remove instances returning non-200 status codes.

Database Health: Monitor PostgreSQL replication lag using pg_stat_replication and connection viability via pg_isready.

Cache Health: Verify Redis availability using redis-cli ping and monitor Sentinel status with sentinel masters to ensure automatic failover capability.

Worker Health: Monitor the Dramatiq task queue depth in PostgreSQL. A growing queue without consumption indicates worker failures requiring investigation.

Summary

  • Authentik servers and workers are stateless, allowing safe horizontal scaling by simply increasing replica counts.
  • PostgreSQL high availability requires primary-replica streaming replication, connection poolers like PgBouncer, and automated failover solutions such as Patroni.
  • Redis must run in Sentinel or Cluster mode to prevent the caching layer from becoming a single point of failure.
  • Dramatiq uses PostgreSQL as its message broker via django-dramatiq-postgres, storing tasks in the database and requiring direct (non-pooled) connections for LISTEN/NOTIFY functionality.
  • Load balancers should use the /api/v3/system/status/ endpoint for health checks to ensure traffic routes only to healthy instances.

Frequently Asked Questions

Does Authentik support active-active database configurations?

Authentik requires a single PostgreSQL primary for write operations, but supports read replicas for query offloading. Configure the primary for writes and replicas for reads using the connection pooler settings in configuration.mdx. True multi-master PostgreSQL configurations are not required or recommended for Authentik deployments.

Can I use Redis Cluster instead of Redis Sentinel for Authentik caching?

Yes, Authentik supports Redis Cluster deployments for high-availability caching. Configure the AUTHENTIK_REDIS__HOST environment variable to point to your cluster's seed nodes. The application uses standard Redis client libraries that handle cluster topology discovery automatically. Ensure your cluster has at least three master nodes with replicas for proper failover support.

Why does Dramatiq need a direct database connection instead of using PgBouncer?

The Dramatiq broker implemented in [broker.py](https://github.com/goauthentik/authentik/tree/main/packages/django-dramatiq-postgres/django_dramatiq_postgres) relies on PostgreSQL's LISTEN/NOTIFY mechanism for real-time task notification. Connection poolers like PgBouncer buffer these notifications, causing workers to miss new tasks or experience delayed processing. Configure a separate database connection string that bypasses the pooler specifically for the Dramatiq broker while allowing the main application to use pooled connections.

How many worker replicas should I run for high availability?

Deploy at least two worker replicas to ensure background tasks continue processing if one worker fails. For production environments handling heavy sync loads or frequent provisioning operations, scale to three or more workers. Monitor the task queue depth in PostgreSQL—if the queue grows consistently during peak hours, increase worker replica counts until the queue stabilizes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →