🚀 Background
Celery is a cron job service commonly used in Django projects. In my case, I used Celery to reset user streaks at midnight (00:00 AM) for my application.
In development, I had to run three terminal windows:
One for the Django server:
python manage.py runserverOne for the Celery worker:
celery -A proj workerOne for the Celery beat:
celery -A proj beat
That setup was a bit complex. So in this blog, I’ll share how I set up Celery as a production-ready service using systemd.
🛠️ Approach
When I first moved my app to production, I used Gunicorn to serve Django, but forgot about Celery. As a result, scheduled tasks didn’t run because both Celery Worker and Celery Beat need to run in parallel.
✅ Option 1: Using tmux
Initially, I used tmux:
SSH into the server.
Start a
tmuxsession and split the window withCtrl + b→%.Run the worker and beat processes in separate panes.
Even after closing SSH, the processes stayed alive (confirmed using htop). This works, but it’s not ideal for long-term use.
✅ Option 2: Using systemd Services
When I got a new VPS, I wanted a better solution. After some research (and help from ChatGPT 😄), I found a reliable approach using systemd services to run Celery in the background.
Reference: Django with Celery in Production
⚙️ 1. Create the Celery Worker Service
Create a new service file:
sudo nano /etc/systemd/system/celery.service Paste the following (replace user, paths, and [celery_app] accordingly):
[Unit] Description=Celery Worker Service After=network.target [Service] Type=simple User=your_username Group=your_username WorkingDirectory=/home/your_username/your_project ExecStart=/home/your_username/.local/share/virtualenvs/your-venv/bin/celery -A [celery_app] worker --loglevel=INFO Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target 👉 Replace:
your_usernamewith your actual Linux username.[celery_app]with the value from yourcelery.pyfile.
Then run:
sudo systemctl daemon-reload sudo systemctl enable celery sudo systemctl start celery 🕒 2. Create the Celery Beat Service
Now create the Beat service:
sudo nano /etc/systemd/system/celery-beat.service Paste the following:
[Unit] Description=Celery Beat Service After=network.target [Service] Type=simple User=your_username Group=your_username WorkingDirectory=/home/your_username/your_project ExecStart=/home/your_username/.local/share/virtualenvs/your-venv/bin/celery -A [celery_app] beat --loglevel=INFO Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target Then run:
sudo systemctl daemon-reload sudo systemctl enable celery-beat sudo systemctl start celery-beat ✅ Check status:
sudo systemctl status celery-beat If you see active (running), it means everything is set up correctly.
🧾 Conclusion
That’s how I set up Celery and Celery Beat in production using systemd. It’s a clean, reliable, and maintainable way to manage background tasks in Django.
📚 References:
Thanks for reading! 🙏 Hope this helps you in your deployment journey.

Top comments (0)