How to set per-message expiration (TTL) in Celery?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Time-To-Live (TTL) is an important feature in message queuing that determines how long a message should remain in the queue before it becomes invalid or expires. In the context of Celery, a powerful asynchronous task queue/job queue based on distributed message passing, setting a per-message TTL can be crucial for handling tasks that should only be relevant for a specific duration. This can be used to avoid executing outdated tasks which can save computational resources and improve overall efficiency.
Understanding Celery and Message Queuing
Celery communicates through messages, typically using a broker like RabbitMQ, Redis, or Amazon SQS. Each message corresponds to a task, which might have different requirements on how long it should wait in the queue before becoming obsolete.
Setting Per-Message TTL
In Celery, setting a TTL for individual messages involves specifying the expiration parameter. This parameter can be defined directly when sending a task. Here's how it can be implemented:
1. Configure Your Celery Instance
First, ensure that your Celery instance is set up and configured to use a broker that supports TTL. Both RabbitMQ and Redis support this feature.
2. Sending Tasks with TTL
When you dispatch a task, you can specify the expires argument to set the TTL (in seconds). After the TTL has passed, the message will be discarded by the message broker if it has not already been consumed.
Alternatively, TTL can be defined in the task decorator, which applies to all instances where that task is called.
Here, another_task will automatically expire if not executed within 300 seconds from being called.
Using Celery’s Configuration
You can also set a default global TTL for all tasks in your Celery configuration like so:
Table: TTL Mechanisms in Celery
| Parameter | Scope | Description |
expires in apply_async() | Per Message | Set a specific TTL for a single message. |
@app.task(expires=...) | Task Default | Set a default TTL for all instances of a specific task. |
task_time_limit | Global Configuration | Terminates any task that runs longer than the specified limit. |
task_soft_time_limit | Global Configuration | Soft limit; task receives a soft time limit exceeded exception. |
Additional Considerations
- Broker Support: Not all brokers might support the TTL feature in the same way. Verify that your broker (RabbitMQ, Redis, etc.) supports TTL settings.
- Resource Cleanup: When using TTL, ensure that resources such as database connections or external APIs that tasks might use have appropriate timeouts or cleanup codes.
- Date and Time Calculation: When passing dates and times to the
expiresargument, ensure they are correctly calculated, taking into account the timezone and server time.
Conclusion
Setting a TTL per message in Celery allows for better control over task execution, particularly useful in scenarios where task data becomes irrelevant after a certain period. Whether you’re managing tasks in real-time systems, handling transient data, or dealing with high-volume task queues, understanding and effectively using TTL can prevent your system from doing unnecessary work, thus saving resources and ensuring up-to-date task execution.
Related reading
- How to set Principal in Kafka console producer/consumer?
- How to set timeout detection on a RabbitMQ server?
- How to set timeout for onFailure event (Spring, Kafka)?
- How to set up autoscaling RabbitMQ Cluster AWS
- How to set shape in placeholder for non-deterministic array size
- How to shutdown celery node
- how to setup basic rabbitmq on kubernetes
- How to setup kafka transactional producer

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.