0Pricing
FastAPI Backend Development Bootcamp · Lesson

Scheduled and Periodic Jobs with Celery Beat

Run recurring jobs using Celery Beat and coordinate cron-style schedules across multiple workers safely.

Why Celery Beat?

Your FastAPI app fires off one-off background tasks with Celery just fine, but some work must run on a schedule: send a digest email every morning, expire abandoned carts every 10 minutes, recompute analytics nightly.

Celery Beat is a scheduler process. It does not execute tasks itself — it wakes up on a tick, decides which tasks are due, and pushes them onto the broker (Redis/RabbitMQ). Your normal celery worker processes pick them up and run them.

  • Beat = the clock that publishes due tasks.
  • Worker = the muscle that runs them.

This separation is the whole reason periodic jobs scale: one Beat, many workers.

Defining the schedule

Schedules live on the Celery app under conf.beat_schedule. Each entry maps a name to a dict with the task path, a schedule (seconds, timedelta, or a crontab), and optional args/kwargs.

The simplest schedule is a fixed interval. Below, the cleanup task runs every 30 seconds. The task path string must match the worker's registered name exactly.

from celery import Celery
from datetime import timedelta

app = Celery("jobs", broker="redis://localhost:6379/0")

@app.task(name="tasks.cleanup_sessions")
def cleanup_sessions():
    # delete expired sessions from the DB
    return "cleaned"

app.conf.beat_schedule = {
    "cleanup-every-30s": {
        "task": "tasks.cleanup_sessions",
        "schedule": timedelta(seconds=30),
    },
}

All lessons in this course

  1. Lightweight Offloading with BackgroundTasks
  2. Wiring Celery Workers to a FastAPI App
  3. Retries, Idempotency and Dead-Letter Handling
  4. Scheduled and Periodic Jobs with Celery Beat
← Back to FastAPI Backend Development Bootcamp