---
title: "Alternativen zu Celery für Django auf Kubernetes"
description: "Suchst du eine schlanke Alternative zu Celery für Django auf Kubernetes? Wir vergleichen Django Celery, RQ, Dramatiq & Huey und zeigen, wie Sie mit KEDA einfach skalieren. Finde die beste Lösung für dein Projekt."
canonical_url: "https://www.blueshoe.de/blog/alternativen-zu-django-celery-in-kubernetes/"
---

Du planst Hintergrundjobs im Cluster und fragst dich, ob es neben Celery 'leichtere' Optionen gibt?

Celery ist mächtig, aber manchmal zu schwergewichtig für einfache Setups. In diesem Artikel schauen wir auf Alternativen wie **Django RQ, Dramatiq und Huey**, erklären, warum **KEDA** eine Schlüsselrolle beim Autoscaling spielt und geben dir **Mini-YAML-Beispiele** für sauberes Deployment mit Probes und Graceful Shutdown.

![Celery Alternativen](/img/blog/celery-alt.png)

## Die vier Optionen im Kurzprofil

*(Mit Links zu Projekten und Repos, damit du weiter eintauchen kannst.)*

### [Celery](https://docs.celeryq.dev/)

Der Klassiker mit großem Ökosystem. Unterstützt Worker und den separaten Scheduler Beat. In großen Setups mit Chains und vielen Integrationen bleibt Celery der Referenzpunkt.

### [Django RQ](https://github.com/rq/django-rq)

Django-freundliche Integration von RQ auf Redis Basis. Worker starten im Django Kontext. In vielen Fällen genügt das Setzen von `DJANGO_SETTINGS_MODULE`. Monitoring ist leicht über [RQ Dashboard](https://github.com/rq/rq-dashboard) oder Admin-Integrationen.

### [Dramatiq](https://dramatiq.io/)

Moderne Defaults mit Fokus auf Zuverlässigkeit. Läuft mit Redis oder RabbitMQ. Die Django Integration [`django_dramatiq`](https://github.com/Bogdanp/django_dramatiq) bringt das Management Kommando `rundramatiq`.

### [Huey](https://huey.readthedocs.io/)

Leichtgewichtig mit eingebautem Scheduler. Saubere Django Integration über das Management Kommando `run_huey` inklusive Auto-Discovery von `tasks.py`.

---

## KEDA in 60 Sekunden

[KEDA](https://keda.sh/) ist der Kubernetes Event Driven Autoscaler.<br />


Er skaliert Deployments und Jobs abhängig von Ereignissen wie Queue-Längen und kann bei Leerlauf bis auf null skalieren. KEDA ergänzt den Horizontal Pod Autoscaler und arbeitet mit ihm zusammen.

Warum ist KEDA so wichtig?

- Du brauchst **kein Polling** im Worker.
- Pods skalieren dynamisch, wenn Jobs in der Queue liegen.
- Bei Leerlauf kannst du die Worker **auf 0 reduzieren** und Ressourcen sparen.

Typische Trigger für Django Worker sind **Redis Lists** sowie **RabbitMQ Queues**. Beide sind als Scaler verfügbar.

---

## Vergleich speziell für Kubernetes

<table>
<thead>
  <tr>
    <th>
      Tool
    </th>
    
    <th>
      Broker
    </th>
    
    <th>
      KEDA Trigger
    </th>
    
    <th>
      Vorteile
    </th>
    
    <th>
      Nachteile
    </th>
    
    <th>
      Beste Wahl wenn
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <strong>
        Celery
      </strong>
    </td>
    
    <td>
      Redis, RabbitMQ
    </td>
    
    <td>
      Redis List oder RabbitMQ Queue
    </td>
    
    <td>
      <strong>
        Sehr ausgereift
      </strong>
      
      , viele Integrationen, Worker plus Beat, breite Community. <strong>
        K8s Plus:
      </strong>
      
       viele Beispiele für Queue-basiertes Autoscaling.
    </td>
    
    <td>
      Mehr Betriebsaufwand, zusätzliche Komponenten wie Beat, sorgfältiges Shutdown Handling nötig.
    </td>
    
    <td>
      Hohe Last, komplexe Chains, vorhandene Celery Erfahrung.
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        Django RQ
      </strong>
    </td>
    
    <td>
      Redis
    </td>
    
    <td>
      Redis List
    </td>
    
    <td>
      <strong>
        Sehr leichter Start
      </strong>
      
      , Admin Integration, wenige bewegliche Teile. <strong>
        K8s Plus:
      </strong>
      
       Listenlänge als simpler KEDA Trigger.
    </td>
    
    <td>
      Geringere Feature Tiefe, Redis Pflicht.
    </td>
    
    <td>
      Web Projekte mit klaren Jobs und schnellem Go Live.
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        Dramatiq
      </strong>
    </td>
    
    <td>
      Redis, RabbitMQ
    </td>
    
    <td>
      Redis List oder RabbitMQ Queue
    </td>
    
    <td>
      <strong>
        Moderne Defaults
      </strong>
      
      , robuste Retries, saubere Django Integration über <code>
        rundramatiq
      </code>
      
      . <strong>
        K8s Plus:
      </strong>
      
       gut kombinierbar mit KEDA je nach Broker.
    </td>
    
    <td>
      Weniger fertige Django UIs, Einarbeitung ins Actor Modell.
    </td>
    
    <td>
      Anspruchsvoll aber schlank, Fokus auf Zuverlässigkeit.
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        Huey
      </strong>
    </td>
    
    <td>
      Redis
    </td>
    
    <td>
      Redis List
    </td>
    
    <td>
      <strong>
        Leichtgewichtig
      </strong>
      
      , Scheduler enthalten, Consumer als Management Kommando. <strong>
        K8s Plus:
      </strong>
      
       simpler Prozess und KEDA Kopplung.
    </td>
    
    <td>
      Kleineres Ökosystem, Monitoring eher minimal.
    </td>
    
    <td>
      Wenige Worker, viele periodische Aufgaben.
    </td>
  </tr>
</tbody>
</table>

---

## Mini YAML Beispiele

### Beispiel A: Celery Worker mit RabbitMQ und KEDA

```yaml
# Deployment für Celery Worker
apiVersion: apps/v1
kind: Deployment
metadata:
  name: celery-worker
spec:
  selector: { matchLabels: { app: celery } }
  template:
    metadata: { labels: { app: celery } }
    spec:
      terminationGracePeriodSeconds: 60
      containers:
        - name: worker
          image: your-registry/app:latest
          command: ["celery","-A","proj","worker","--loglevel=info"]
          env:
            - name: RABBITMQ_HOST
              valueFrom:
                secretKeyRef: { name: rmq, key: amqp_uri }
---
# ScaledObject für RabbitMQ Queue
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: celery-rabbit
spec:
  scaleTargetRef: { name: celery-worker }
  minReplicaCount: 0
  maxReplicaCount: 20
  triggers:
    - type: rabbitmq
      metadata:
        hostFromEnv: RABBITMQ_HOST
        queueName: celery
        protocol: amqp
        mode: QueueLength
        value: "20"
      authenticationRef:
        name: rmq-auth
```

---

### Beispiel B: Django RQ Worker plus KEDA Redis List Scaler

```yaml
# Deployment für RQ Worker
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rq-worker
spec:
  selector: { matchLabels: { app: rq } }
  template:
    metadata: { labels: { app: rq } }
    spec:
      terminationGracePeriodSeconds: 60
      containers:
        - name: worker
          image: your-registry/app:latest
          command: ["bash","-lc","DJANGO_SETTINGS_MODULE=config.settings rq worker default"]
          env:
            - name: REDIS_HOST
              value: "redis:6379"
---
# KEDA ScaledObject mit Redis List Trigger
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: rq-scale
spec:
  scaleTargetRef: { name: rq-worker }
  minReplicaCount: 0
  maxReplicaCount: 10
  triggers:
    - type: redis
      metadata:
        addressFromEnv: REDIS_HOST
        listName: default
        listLength: "20"  # Skalierung ab 20 Jobs
```

---

### Beispiel C: Dramatiq unter Django mit Redis

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dramatiq-worker
spec:
  selector: { matchLabels: { app: dramatiq } }
  template:
    metadata: { labels: { app: dramatiq } }
    spec:
      terminationGracePeriodSeconds: 60
      containers:
        - name: worker
          image: your-registry/app:latest
          command: ["python","manage.py","rundramatiq","--processes","2","--threads","8"]
          env:
            - name: REDIS_HOST
              value: "redis:6379"
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: dramatiq-scale
spec:
  scaleTargetRef: { name: dramatiq-worker }
  minReplicaCount: 0
  maxReplicaCount: 10
  triggers:
    - type: redis
      metadata:
        addressFromEnv: REDIS_HOST
        listName: default
        listLength: "10"
```

---

### Beispiel D: Huey Worker mit Redis

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: huey-worker
spec:
  selector: { matchLabels: { app: huey } }
  template:
    metadata: { labels: { app: huey } }
    spec:
      terminationGracePeriodSeconds: 60
      containers:
        - name: worker
          image: your-registry/app:latest
          command: ["python","manage.py","run_huey"]
          env:
            - name: REDIS_HOST
              value: "redis:6379"
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: huey-scale
spec:
  scaleTargetRef: { name: huey-worker }
  minReplicaCount: 0
  maxReplicaCount: 5
  triggers:
    - type: redis
      metadata:
        addressFromEnv: REDIS_HOST
        listName: default
        listLength: "5"
```

---

## Kubernetes Betriebsaspekte, die zählen

### Broker deployen

Redis und RabbitMQ bekommst du stabil per [Helm Chart](https://artifacthub.io/) oder Operator. Für RabbitMQ gibt es zusätzlich einen offiziellen [Cluster Operator](https://www.rabbitmq.com/kubernetes/operator/).

### Probes konfigurieren

Setze **Readiness, Liveness** und bei längeren Starts eine **Startup Probe**. Beispiel:

```yaml
livenessProbe:
  exec: { command: ["pgrep", "rq"] }
  initialDelaySeconds: 20
  periodSeconds: 10
```

So verhinderst du Deadlocks und Traffic an nicht bereite Pods.

### Graceful Shutdown

Nutze `terminationGracePeriodSeconds` und bei Bedarf einen `preStop` Hook, damit laufende Tasks sauber zu Ende laufen:

```yaml
lifecycle:
  preStop:
    exec:
      command: ["bash","-c","kill -TERM 1 && sleep 30"]
```

Kubernetes beendet Container nach Ablauf der Grace Period in jedem Fall – plane also Puffer.

### KEDA Installation

KEDA lässt sich per [Helm Chart](https://keda.sh/docs/) oder YAML installieren. Danach definierst du **ScaledObjects** oder **ScaledJobs** pro Worker.

---

## Code Beispiele für Tasks

Damit du den Unterschied auch im Django Code siehst:

### Celery

```python
from celery import shared_task

@shared_task
def send_email(user_id):
    # klassische Celery Task
    ...
```

### Django RQ

```python
import django_rq

def send_email(user_id):
    ...

# Task in die Queue legen
queue = django_rq.get_queue('default')
queue.enqueue(send_email, user.id)
```

### Dramatiq

```python
import dramatiq

@dramatiq.actor
def send_email(user_id):
    ...

# Task dispatchen
send_email.send(user.id)
```

### Huey

```python
from huey.contrib.djhuey import task

@task()
def send_email(user_id):
    ...

# Task aufrufen
send_email(user.id)
```

---

## Ausfallhandling in Kubernetes Clustern

Früher oder später passiert’s: Ein Worker geht down oder der Broker fällt aus. Damit deine Tasks trotzdem sauber weiterlaufen, brauchst du etwas Absicherung. So kannst du vorgehen:

### Wenn ein Worker abstürzt

Kubernetes stellt deine Pods automatisch mit `restartPolicy: Always` wieder her. Wichtig ist jedoch, dass Jobs erst dann aus der Queue entfernt werden, wenn sie wirklich verarbeitet sind. Andernfalls gehen Tasks verloren.

Alle vier Tools (Celery, RQ, Dramatiq, Huey) unterstützen eingebaute Retries. Diese solltest du aktiv einsetzen.

Ein Beispiel für ein RQ‑Worker‑Deployment:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rq‑worker
spec:
  replicas: 2
  selector: { matchLabels: { app: rq } }
  template:
    metadata: { labels: { app: rq } }
    spec:
      restartPolicy: Always
      containers:
        - name: worker
          image: your‑registry/app:latest
          command: ["rq","worker","default"]
```

Wenn ein Pod abstürzt, startet Kubernetes ihn einfach neu. Die offenen Jobs bleiben in Redis liegen und werden vom nächsten Worker übernommen.

---

### Wenn der Broker ausfällt

Ohne Redis oder RabbitMQ läuft nichts. Deshalb solltest du diese Komponenten hochverfügbar betreiben.

#### Redis als StatefulSet

Ein Deployment allein reicht nicht aus, wenn Daten dauerhaft gespeichert werden müssen. Ein StatefulSet sorgt dafür, dass Redis‑Pods stabile Namen und ein eigenes Volume haben. Damit bleibt die Queue auch nach Neustarts bestehen.

Kurz gesagt: StatefulSets geben Pods eine feste Identität und persistenten Speicher.

#### RabbitMQ mit replizierten Queues

RabbitMQ‑Queues sind normalerweise an einen Node gebunden. Fällt dieser Node oder Pod aus, ist die Queue verschwunden. Mit Quorum Queues, also replizierten und ausfallsicheren Queues auf Basis des Raft‑Protokolls, bist du sicherer aufgestellt. Der RabbitMQ Kubernetes Operator erleichtert dir den Aufbau eines hochverfügbaren Clusters.

Der Vorteil ist klar: Wenn ein Pod ausfällt, übernimmt ein anderer, ohne dass deine Worker davon viel mitbekommen.

---

### Kubernetes‑Tools, die du nicht vergessen solltest

- **PodDisruptionBudget (PDB):** sorgt dafür, dass bei Updates nicht zu viele Pods gleichzeitig ausfallen.
- **Readiness Probes:** stellen sicher, dass nur gesunde Pods Jobs bearbeiten.
- **Graceful Shutdown:** gibt deinen Workern Zeit, um Tasks bei SIGTERM zu Ende zu bringen.
- **Backoff und Retries:** ermöglichen es Workern, automatisch wieder zu verbinden, wenn der Broker kurzzeitig nicht erreichbar ist.

---

Mit diesem Setup bist du für die häufigsten Fehlerquellen im Cluster gut vorbereitet, egal ob Worker oder Broker einmal ausfallen.

## Entscheidungsleitfaden

- **Einfach und schnell mit Redis:** Django RQ oder Huey. Kopple über den KEDA Redis List Scaler.
- **Robust mit flexibler Broker Wahl:** Dramatiq. Nimm Redis oder RabbitMQ und binde KEDA entsprechend an.
- **Großes Setup mit vorhandenem Know-how:** Celery mit ScaledObjects je Queue und optional Beat oder django-celery-beat für Periodics.

Migrationen sind möglich: Viele Task-Definitionen lassen sich mit geringem Aufwand portieren, auch wenn Retry/ACK-Mechanismen unterschiedlich umgesetzt sind.

---

## FAQ

### 1. Was ist KEDA und wofür nutze ich es?

KEDA skaliert Workloads anhand externer Ereignisse wie Queue Länge und ermöglicht Scale to Zero. Es ergänzt den Horizontal Pod Autoscaler.

### 2. Kann ich alle vier Tools mit KEDA autoscalen?

Ja. Über den Redis Lists Scaler oder den RabbitMQ Queue Scaler, je nach Broker.

### 3. Wie wähle ich den passenden Broker?

Redis ist schnell bereitgestellt und genügt oft für Web Projekte. RabbitMQ lohnt sich bei komplexem Routing oder bestehender AMQP Erfahrung.

### 4. Brauche ich für Celery einen separaten Scheduler?

Für periodische Aufgaben nutzt Celery den Scheduler Beat. Mit [django-celery-beat](https://github.com/celery/django-celery-beat) kannst du Zeitpläne im Django Admin pflegen.

### 5. Wie starte ich Dramatiq in Django sauber?

Über `python manage.py rundramatiq` aus `django_dramatiq`. Das Kommando ist für die Django Integration gedacht.

### 6. Gibt es Dashboards für Django RQ?

Ja. Es gibt [rq-dashboard](https://github.com/rq/rq-dashboard) als Standalone sowie Integrationen für den Django Admin.

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
