Defining Interval Schedules
Interval schedules are the most straightforward way to run periodic tasks in Celery. By using the schedule class, you can define tasks that execute at a fixed frequency, such as every 30 seconds or every hour.
In this tutorial, you will learn how to define these intervals using both raw numbers and timedelta objects, and how to configure them within your Celery application.
Prerequisites
To follow this guide, you need a Celery app instance defined in your project.
from celery import Celery
app = Celery('my_project')
Step 1: Define a Basic Interval in Seconds
The simplest way to create an interval schedule is to pass a number of seconds to the schedule class.
from celery.schedules import schedule
# Create a schedule that triggers every 10 seconds
every_ten_seconds = schedule(run_every=10.0)
print(f"Schedule frequency: {every_ten_seconds.human_seconds}")
The run_every argument accepts a float or int. When you instantiate schedule(10.0), Celery internally converts this to a timedelta object. The human_seconds property provides a readable string representation of the interval (e.g., "10.00 seconds").
Step 2: Use Timedelta for Complex Intervals
For longer intervals, using datetime.timedelta makes your code more readable.
from datetime import timedelta
from celery.schedules import schedule
# Create a schedule that triggers every 1 hour and 30 minutes
complex_interval = schedule(run_every=timedelta(hours=1, minutes=30))
Using timedelta is the recommended approach for any interval longer than a few minutes, as it clearly communicates the intent of the schedule.
Step 3: Configure the Beat Schedule
Once you have defined your intervals, you must add them to the beat_schedule setting in your Celery configuration. Celery's maybe_schedule utility allows you to use shorthand values (like raw numbers or timedelta objects) directly in the configuration dictionary.
app.conf.beat_schedule = {
'sync-data-every-30-seconds': {
'task': 'tasks.sync_data',
'schedule': 30.0, # Shorthand for schedule(30.0)
},
'cleanup-every-day': {
'task': 'tasks.cleanup',
'schedule': timedelta(days=1), # Shorthand for schedule(timedelta(days=1))
},
}
When the Celery Beat service starts, it iterates through this dictionary and converts these shorthand values into formal celery.schedules.schedule objects.
Step 4: Align Execution with Relative Schedules
By default, interval schedules are calculated based on the time the Beat service started. If you want the execution time to be rounded to the resolution of the interval, use the relative argument.
from datetime import timedelta
from celery.schedules import schedule
# This schedule will align to the minute boundary (e.g., 12:01:00, 12:02:00)
aligned_schedule = schedule(run_every=timedelta(minutes=1), relative=True)
When relative=True, the remaining_estimate calculation rounds the next run time. This is useful if you want multiple tasks with the same interval to synchronize their execution times.
Step 5: Adjust Scheduling Precision
The precision of your interval is affected by the beat_max_loop_interval setting. This setting determines the maximum time the scheduler sleeps between checking if tasks are due.
# Ensure the scheduler checks for due tasks at least every 5 seconds
app.conf.beat_max_loop_interval = 5
If you have a task scheduled to run every 10 seconds but beat_max_loop_interval is set to 300 (the default 5 minutes), your task might experience significant drift if the scheduler is sleeping. For high-frequency tasks, ensure this setting is lower than your smallest interval.
Summary of Results
You have now configured periodic tasks using interval schedules. Your tasks will:
- Run at the fixed frequency defined in
run_every. - Be automatically managed by the Celery Beat service via the
beat_scheduleconfiguration. - Optionally align to interval boundaries if
relative=Trueis used.
To start the scheduler and see your intervals in action, run the following command in your terminal:
celery -A my_project beat -l info