Django Celery Expert
Instructions
Step 1: Classify the Request
Identify the task category from the request:
- Django integration — transaction safety, ORM patterns, testing, request correlation → read
references/django-integration.md
- Task design — new tasks, calling patterns, chains/groups/chords, idempotency → read
references/task-design-patterns.md
- Configuration — broker setup, result backend, worker settings, queue routing → read
references/configuration-guide.md
- Error handling — retries, backoff, dead letter queues, timeouts → read
references/error-handling.md
- Periodic tasks — Celery Beat, crontab schedules, dynamic schedules, timezone handling → read
references/periodic-tasks.md
- Monitoring — Flower, Prometheus, logging, debugging stuck tasks → read
references/monitoring-observability.md
- Production deployment — scaling, supervision, containers, health checks → read
references/production-deployment.md
If the request spans multiple categories, read all relevant reference files before continuing.
Step 2: Read the Reference File(s)
Read each reference file identified in Step 1. Do not proceed to implementation without reading the relevant reference.
Step 3: Implement
Apply the patterns from the reference file. Before presenting the solution, verify:
- Task arguments are serializable (pass IDs, not model instances)
- Tasks with retries enabled are idempotent
- Errors are logged with context
- Long-running tasks have timeouts configured
Examples
Basic Background Task
Request: "Send welcome emails in the background after user registration"
# tasks.py
from celery import shared_task
from django.core.mail import send_mail
@shared_task(bind=True, max_retries=3)
def send_welcome_email(self, user_id):
from users.models import User
try:
user = User.objects.get(id=user_id)
send_mail(
subject="Welcome!",
message=f"Hi {user.name}, welcome to our platform!",
from_email="noreply@example.com",
recipient_list=[user.email],
)
except User.DoesNotExist:
pass
except Exception as exc:
raise self.retry(exc=exc, countdown=60 * (2 ** self.request.retries))
# views.py — queue only after the transaction commits
from django.db import transaction
def register(request):
user = User.objects.create(...)
transaction.on_commit(lambda: send_welcome_email.delay(user.id))
return redirect("dashboard")
Task with Progress Tracking
Request: "Process a large CSV import with progress updates"
@shared_task(bind=True)
def import_csv(self, file_path, total_rows):
from myapp.models import Record
with open(file_path) as f:
reader = csv.DictReader(f)
for i, row in enumerate(reader):
Record.objects.create(**row)
if i % 100 == 0:
self.update_state(
state="PROGRESS",
meta={"current": i, "total": total_rows},
)
return {"status": "complete", "processed": total_rows}
# Poll progress
result = import_csv.AsyncResult(task_id)
if result.state == "PROGRESS":
progress = result.info.get("current", 0) / result.info.get("total", 1)
Workflow with Chains
Request: "Process an order: validate inventory, charge payment, then send confirmation"
from celery import chain
@shared_task
def validate_inventory(order_id):
order = Order.objects.get(id=order_id)
if not order.items_in_stock():
raise ValueError("Items out of stock")
return order_id
@shared_task
def charge_payment(order_id):
order = Order.objects.get(id=order_id)
order.charge()
return order_id
@shared_task
def send_confirmation(order_id):
Order.objects.get(id=order_id).send_confirmation_email()
def process_order(order_id):
chain(
validate_inventory.s(order_id),
charge_payment.s(),
send_confirmation.s(),
).delay()
Source: wilfredinni/django-starter-template — distributed by TomeVault.
1---2name: django-celery-expert3description: Expert Django Celery guidance for asynchronous task processing. Use when designing background tasks, configuring Celery workers, handling task retries and errors, optimizing Celery performance, implementing periodic tasks with Celery Beat, or setting up production monitoring for Celery. Do not use for general Django questions unrelated to Celery, non-Celery task systems (Django Q, Huey, RQ), ML/data pipeline orchestration (Airflow, Prefect), or frontend and API-only concerns. Follows Vinta's Django Celery best practices. Use when this capability is needed.4---56# Django Celery Expert78## Instructions910### Step 1: Classify the Request1112Identify the task category from the request:1314- **Django integration** — transaction safety, ORM patterns, testing, request correlation → read `references/django-integration.md`15- **Task design** — new tasks, calling patterns, chains/groups/chords, idempotency → read `references/task-design-patterns.md`16- **Configuration** — broker setup, result backend, worker settings, queue routing → read `references/configuration-guide.md`17- **Error handling** — retries, backoff, dead letter queues, timeouts → read `references/error-handling.md`18- **Periodic tasks** — Celery Beat, crontab schedules, dynamic schedules, timezone handling → read `references/periodic-tasks.md`19- **Monitoring** — Flower, Prometheus, logging, debugging stuck tasks → read `references/monitoring-observability.md`20- **Production deployment** — scaling, supervision, containers, health checks → read `references/production-deployment.md`2122If the request spans multiple categories, read all relevant reference files before continuing.2324### Step 2: Read the Reference File(s)2526Read each reference file identified in Step 1. Do not proceed to implementation without reading the relevant reference.2728### Step 3: Implement2930Apply the patterns from the reference file. Before presenting the solution, verify:3132- Task arguments are serializable (pass IDs, not model instances)33- Tasks with retries enabled are idempotent34- Errors are logged with context35- Long-running tasks have timeouts configured3637## Examples3839### Basic Background Task4041**Request:** "Send welcome emails in the background after user registration"4243```python44# tasks.py45from celery import shared_task46from django.core.mail import send_mail4748@shared_task(bind=True, max_retries=3)49def send_welcome_email(self, user_id):50 from users.models import User5152 try:53 user = User.objects.get(id=user_id)54 send_mail(55 subject="Welcome!",56 message=f"Hi {user.name}, welcome to our platform!",57 from_email="noreply@example.com",58 recipient_list=[user.email],59 )60 except User.DoesNotExist:61 pass62 except Exception as exc:63 raise self.retry(exc=exc, countdown=60 * (2 ** self.request.retries))646566# views.py — queue only after the transaction commits67from django.db import transaction6869def register(request):70 user = User.objects.create(...)71 transaction.on_commit(lambda: send_welcome_email.delay(user.id))72 return redirect("dashboard")73```7475### Task with Progress Tracking7677**Request:** "Process a large CSV import with progress updates"7879```python80@shared_task(bind=True)81def import_csv(self, file_path, total_rows):82 from myapp.models import Record8384 with open(file_path) as f:85 reader = csv.DictReader(f)86 for i, row in enumerate(reader):87 Record.objects.create(**row)88 if i % 100 == 0:89 self.update_state(90 state="PROGRESS",91 meta={"current": i, "total": total_rows},92 )9394 return {"status": "complete", "processed": total_rows}959697# Poll progress98result = import_csv.AsyncResult(task_id)99if result.state == "PROGRESS":100 progress = result.info.get("current", 0) / result.info.get("total", 1)101```102103### Workflow with Chains104105**Request:** "Process an order: validate inventory, charge payment, then send confirmation"106107```python108from celery import chain109110@shared_task111def validate_inventory(order_id):112 order = Order.objects.get(id=order_id)113 if not order.items_in_stock():114 raise ValueError("Items out of stock")115 return order_id116117@shared_task118def charge_payment(order_id):119 order = Order.objects.get(id=order_id)120 order.charge()121 return order_id122123@shared_task124def send_confirmation(order_id):125 Order.objects.get(id=order_id).send_confirmation_email()126127def process_order(order_id):128 chain(129 validate_inventory.s(order_id),130 charge_payment.s(),131 send_confirmation.s(),132 ).delay()133```134135---136> Source: [wilfredinni/django-starter-template](https://github.com/wilfredinni/django-starter-template) — distributed by [TomeVault](https://tomevault.io).137<!-- tomevault:4.0:skill_md:2026-07-04 -->