Using Celery + Redis for Background Jobs in Django (A Practical Walkthrough)
If your Django app needs to send emails, generate reports, process uploaded files, or run any task that shouldn't block a user's request, **Celery** paired with **Redis** as the message broker is the standard solution. This post covers the practical setup and the mistakes that trip people up.
Why you need a background task queue
Without one, a slow operation (like generating a PDF report or calling a third-party API) runs inside the request-response cycle — the user waits, and if it fails or times out, they see an error. Offloading it to Celery lets the API respond immediately while the work happens in the background.
Basic setup
- >Install Celery and Redis: `pip install celery redis`
- >Configure Celery in your Django project with Redis as the broker (`CELERY_BROKER_URL = 'redis://localhost:6379/0'`)
- >Define tasks with the `@shared_task` decorator in a `tasks.py` file inside each app
- >Run a worker process alongside your Django server: `celery -A your_project worker -l info`
Adding scheduled tasks with Celery Beat
For recurring jobs (e.g. "clean up expired sessions every night" or "refresh a cache every hour"), Celery Beat runs tasks on a schedule, similar to a cron job, but managed inside your Django project and stored in your task code rather than the server's crontab.
Common pitfalls
- >Forgetting to run the worker in production. Tasks queue up in Redis but never execute if the worker isn't running as its own process/service.
- >Passing Django model instances directly into tasks. Pass IDs instead, and re-fetch the object inside the task — model instances don't serialize reliably and the data may be stale by the time the task runs.
- >No retry logic. Network calls and third-party API integrations fail sometimes. Use Celery's built-in `retry` with exponential backoff instead of letting a task fail silently.
- >Not monitoring the queue. Use a tool like Flower (a web-based Celery monitor) so you can see task failures instead of finding out from a user complaint.
FAQ
Do I need Redis specifically, or can I use RabbitMQ? Either works as a Celery broker. Redis is simpler to set up and is a good default; RabbitMQ offers more advanced message-routing features that most small-to-medium projects don't need.
Can Celery tasks talk to my Django database? Yes — as long as Django is properly configured in the Celery worker's settings, tasks can query and update the database like any other part of your app.
How do I test Celery tasks locally without running a worker? Set `CELERY_TASK_ALWAYS_EAGER = True` in development settings — this runs tasks synchronously in the same process, which is convenient for quick testing (but don't use it in production).
Author: Nayan Kalola
Python Backend Developer