Sitemap
Vinay Billa

Vinay Billa

Task Queues Made Simple: Offloading Work with Celery or RQ

3 min readAug 4, 2026

--

Introduction

Modern web applications often need to handle background tasks like sending emails, processing images, or running analytics. If these tasks run synchronously, users experience delays, and servers get overloaded. This is where task queues come in.

Task queues let applications offload time-consuming operations to the background, freeing up the main thread to handle more requests efficiently. Two of the most popular task queue libraries in Python are Celery and Redis Queue (RQ).

Get Vinay Billa’s stories in your inbox

Join Medium for free to get updates from this writer.

In this article, we’ll cover:

  • Why task queues are needed
  • How Celery and RQ work
  • Setting up a simple task queue with both
  • When to use Celery vs. RQ

By the end, you’ll have a solid understanding of how to implement background jobs in your application.

Why Use a Task Queue?

Many operations in a web app don’t need to happen immediately. For example:

  • Sending email confirmations after a user registers
  • Resizing and compressing images after upload
  • Running scheduled database maintenance
  • Processing payments without blocking the user

If these tasks run synchronously, the user waits while they complete, making the app feel slow. Task queues solve this by running tasks asynchronously in the background.

How Task Queues Work

A task queue has three main components:

  1. Producer: Adds a task to the queue (usually from the web app).
  2. Queue (Broker): Stores pending tasks (e.g., Redis or RabbitMQ).
  3. Worker: Picks up tasks from the queue and executes them.

Example Flow

  1. A user uploads a profile picture.
  2. The app adds a task to the queue: “Resize this image.”
  3. A background worker picks up the task and processes it.
  4. The user gets an instant response: “Your image is being processed.”
  5. Once complete, the image is updated in the database.

Celery: A Powerful Task Queue

Celery is the most widely used task queue in Python. It supports:
✅ Multiple brokers (Redis, RabbitMQ)
✅ Periodic tasks (via Celery Beat)
✅ Task retries for handling failures

Setting Up Celery with Redis

  1. Install Celery and Redis:
pip install celery redis

Start Redis (if not running):

redis-server

2. Define a Celery worker in tasks.py:

from celery import Celery  
app = Celery("tasks", broker="redis://localhost:6379/0")
@app.task def send_email(user_email):
print(f"Sending email to {user_email}")
return "Email sent!"

3. Start the Celery worker:

celery -A tasks worker --loglevel=info

4. Run a task from Python:

from tasks import send_email  
send_email.delay("test@example.com")

Redis Queue (RQ): A Lightweight Alternative

RQ (Redis Queue) is a simpler alternative to Celery, built specifically for Redis. It’s easier to set up but lacks advanced features like periodic tasks.

Setting Up RQ

  1. Install RQ:
pip install rq

2. Define a background job in tasks.py:

import time from redis 
import Redis from rq import
Queue redis_conn = Redis()
queue = Queue(connection=redis_conn)

def long_task():
time.sleep(5)
print("Task complete!")
return "Done"

job = queue.enqueue(long_task)

3. Start an RQ worker:

rq worker

4. Enqueue a task from Python:

from tasks import long_task, queue  queue.enqueue(long_task)

Celery vs. RQ: Which One to Use?

FeatureCeleryRQEase of setupComplexSimpleBroker SupportRedis, RabbitMQ, SQSRedis onlyPeriodic TasksYes (Celery Beat)NoTask RetriesYesNoMonitoring DashboardYesYes (via rq-dashboard)Best forLarge-scale applicationsSmall projects, simple tasks.

When to Choose Celery

  • You need complex workflows and periodic tasks.
  • You need task retries and error handling.
  • You have high-volume background jobs.

When to Choose RQ

  • You want a simple queue with minimal setup.
  • You’re already using Redis and don’t need RabbitMQ.
  • You have low-frequency background tasks.

Common Mistakes to Avoid

❌ Not Using a Broker: A task queue needs a fast, reliable broker like Redis.
❌ Blocking the Main Thread: Make sure tasks run asynchronously.
❌ Ignoring Task Failures: Set up retry mechanisms for failures.
❌ Overloading Workers: Too many tasks at once can slow down the system.

Final Thoughts

Task queues are a must-have for handling background jobs efficiently. Whether you choose Celery or RQ, offloading long-running tasks will improve performance and scalability.

Next Steps

  • Integrate Celery or RQ into your project.
  • Experiment with periodic tasks and task retries.
  • Monitor task performance using dashboards.

--

--