Time limits and revoking tasks

Celery · Advanced · 10 min

A single hung task can occupy a worker slot forever, and limits keep the system responsive.

Celery offers two limits, per task (@app.task(soft_time_limit=60, time_limit=90)) or globally (task_soft_time_limit, task_time_limit):

  • The soft time limit raises SoftTimeLimitExceeded inside the task, giving it a chance to clean up (delete temp files, mark the job failed) and exit.
  • The hard time limit kills the worker child process and replaces it. No cleanup; the task fails with TimeLimitExceeded.

Set the hard limit a bit above the soft one. Time limits are enforced by the prefork pool using signals; other pools have limited or no support, and limits don't work on Windows.

Time limits complement, not replace, timeouts in your own code: always pass timeout= to HTTP clients and database calls, which fail faster and more precisely.

Revoking: result.revoke() or app.control.revoke(task_id) tells workers to skip a task that hasn't started. revoke(task_id, terminate=True) also kills a running task's process, a blunt last resort. Revocations are kept in worker memory, so they're lost when all workers restart unless you configure persistent revokes (--statedb).

Use expires when calling tasks that are pointless after a deadline; it's cheaper than revoking.

Example

import time
from celery import Celery
from celery.exceptions import SoftTimeLimitExceeded

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

@app.task(soft_time_limit=30, time_limit=40)
def render_video(job_id):
    try:
        for frame in range(10_000):
            time.sleep(0.01)              # real work here
        return "done"
    except SoftTimeLimitExceeded:
        print(f"job {job_id}: out of time, cleaning up")
        # remove temp files, mark job as failed in the DB
        raise

# r = render_video.delay(7)
# r.revoke()                          # skip it if not started yet
# app.control.revoke(r.id, terminate=True)   # kill it if running

Remember

  • Soft limit raises SoftTimeLimitExceeded so the task can clean up
  • Hard limit kills the child process, no cleanup
  • Limits rely on the prefork pool's signals
  • revoke() skips pending tasks; terminate=True kills running ones

Watch out for

  • Catching SoftTimeLimitExceeded with a bare except: Exception and continuing the work until the hard kill.

Check yourself

  1. What happens when a task hits its hard time_limit?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.celeryq.dev/en/stable/userguide/workers.html#time-limits