2 min read

Prioritizing Tasks with Celery Queues

By default, Celery sends all tasks to a single queue named celery. To prioritize specific tasks (like sending a password reset email immediately vs. generating a daily report), you should use Routing and multiple Queues.

1. Defining Queues

You don't strictly need to define queues upfront; Celery creates them automatically if you route a task to them. However, it is good practice to define them in your configuration.

from celery import Celery
from kombu import Queue, Exchange

app = Celery('tasks', broker='redis://localhost:6379/0')

# Optional: Explicitly define queues
app.conf.task_queues = (
    Queue('default', Exchange('default'), routing_key='default'),
    Queue('high_priority', Exchange('high_priority'), routing_key='high_priority'),
    Queue('low_priority', Exchange('low_priority'), routing_key='low_priority'),
)

# Set the default queue
app.conf.task_default_queue = 'default'

2. Routing Tasks

You can assign tasks to queues in two ways:

A. Automatic Routing (Configuration)

This is the cleanest method. You map tasks to queues in your Celery config.

app.conf.task_routes = {
    'tasks.send_email': {'queue': 'high_priority'},
    'tasks.generate_report': {'queue': 'low_priority'},
    # All other tasks go to 'default'
}

B. Manual Routing (At Call Time)

You can specify the queue when calling the task.

from tasks import generate_report

# Send to high priority queue just this once
generate_report.apply_async(args=['2023-10-31'], queue='high_priority')

3. Consuming from Queues

Now that tasks are in different queues, you need to tell your workers how to handle them.

Run separate worker instances for different queues. This guarantees that high-priority tasks always have dedicated resources.

Terminal 1 (High Priority Worker):

celery -A tasks worker -Q high_priority --hostname=high_worker@%h

Terminal 2 (Default/Low Priority Worker):

celery -A tasks worker -Q default,low_priority --hostname=default_worker@%h

programming/python/celery