Transactional Outbox pattern for Celery tasks in Django.
- Durable persistence for committed task intents
- Duplicate-tolerant relay recovery
- Automatic retry with capped exponential backoff
- Dead letter queue for exhausted retries
- Structlog & Sentry trace propagation
- StatsD metrics
- Django admin integration
CI exercises Django 4.2 and 5.2 in the general matrix, plus dedicated live-broker smoke coverage for Django 5.0 and 5.1. The support claims in this repository stay aligned with those explicit lanes.
Canonical coverage is published from the Py3.12 / Django 5.2 / Celery 5.6 / PostgreSQL lane in GitHub Actions.
pip install django-celery-outbox# settings.py
INSTALLED_APPS = [..., 'django_celery_outbox']
CELERY_OUTBOX_APP = 'myproject.celery.app'
# celery.py
from django_celery_outbox import OutboxCelery
app = OutboxCelery('myproject')python manage.py migrate
python manage.py check
python manage.py celery_outbox_relayCommitted rows stay in the outbox until the relay publishes them or dead-letters them, but
consumers still need to be idempotent. If the relay crashes after a broker publish and before
cleanup, stale-timeout recovery can reclaim and resend the row. Stronger end-to-end guarantees
still depend on broker confirms; without publisher confirms, the broker can fail ambiguously
after Celery.send_task() returns.
See Security Guide for PII handling, traceback logging, and DLQ retention.
MIT