Django production problems / background jobs

Celery task stuck or not running? Find out why.

Follow the task from producer to broker to worker. Seven checks help you find where it stopped.

For Django + Celery · Safe diagnostic order · No task arguments needed

Jump to worker inspection commands · Updated 2026-10-26

Start with the symptom

“Pending” does not always mean your task is waiting

Celery uses PENDING both for a task that may be waiting and for a task ID the result backend does not know. So checking AsyncResult.state alone cannot tell you where the work stopped.

Build the timeline instead: did Django publish the message, did the broker accept it, did a worker consume the correct queue, did execution start, and did a terminal state reach the result backend? The first missing transition points to the likely cause.

Primary references: Celery’s official documentation for task states, monitoring workers and events, and the official Django Tasks framework.

Seven checks, in order

Where did the Celery task stop?

Do not restart everything and hope. Find the first missing step between publish and completion, then investigate only that part of the chain.

Instant AI Diagnostic Prompt

Claude Code / Cursor / Windsurf

Paste this into your AI coding agent to diagnose stuck Celery tasks in your repository:

Diagnose why my Celery tasks are stuck. Follow these checks:
1. Verify tasks are called via delay()/apply_async() outside uncommitted DB transactions.
2. Run `celery -A <app> inspect active_queues` and `inspect registered` to confirm worker routing.
3. Check for blocking socket/DB calls without timeouts, or memory limits killing worker processes.

01 / PUBLISH

Was the task actually sent?

Confirm that the call reached delay() or apply_async() and was not skipped by transaction rollback, conditional code or an earlier exception.

02 / WORKER

Is a worker consuming this queue?

A running process may listen to another queue. Check active workers, their subscribed queues and whether every slot is occupied by long-running work.

03 / ROUTING

Does the worker know the task?

Compare the published task name with the worker’s registered tasks. Then check routing keys, queue names and imports after the latest deploy.

04 / RESULT

Is PENDING only missing state?

Verify the result backend and task ID. A missing or expired result also appears as PENDING, even when no message is waiting.

05 / EXECUTION

Is the task blocked inside its work?

Inspect database locks, network calls without timeouts, large payloads and exhausted connection pools. A started task is a different problem from a queued task.

06 / RECOVERY

Is it retrying or timing out forever?

Inspect retry reason, backoff, maximum retries and soft or hard time limits. Repeated retries can look like a queue that never drains.

07 / SCHEDULE

If it is periodic, did Celery Beat publish it?

Treat scheduling and execution separately. First prove Beat emitted the due task once; then repeat the broker, queue and worker checks above. Also verify timezone and duplicate scheduler instances.

Automated background job monitoring

Tired of Celery tasks failing silently in production?

FetchNode records failures, retries and missing completion for instrumented jobs. Verify the signals and configured alerts on your website. Start with one website free, with no credit card.

Start free Celery alerts →

Inspect before changing anything

Three commands to check the worker path

Run these from the same deployment environment as the worker. Replace your_project with the Celery application module used in your worker startup command. Use the same broker configuration; do not paste broker credentials into a shared terminal transcript.

These are inspection requests, not task submissions. Remote control must be enabled and supported by your broker transport. A missing reply can also mean a timeout or a busy worker.

1. Can a worker answer?

celery -A your_project inspect --timeout=5 ping

A responding worker reports pong. If none reply, check the worker process, broker connection and remote-control support. No reply does not prove a task failed.

2. Does it consume the intended queue?

celery -A your_project inspect --timeout=5 active_queues

Compare returned queue names with your task routing. For example, a task routed to billing needs a worker consuming that queue; a reply listing only celery does not establish that.

3. Is the task name registered?

celery -A your_project inspect --timeout=5 registered

Look for the exact task name published by Django, such as billing.tasks.send_invoice. If missing, inspect imports, task autodiscovery and whether producer and worker run the intended release.

After correcting a mismatch, verify the original task's state and whether it may already have produced a side effect. In a separate staging project, use one harmless test task to confirm publish, execution and the expected outcome. A healthy worker reply alone is not end-to-end verification.

Command reference reviewed against Celery 5.6 documentation: worker remote control and limitations and inspection commands. Queue and task names above are examples.

Keep the evidence, not another guess

Select and copy this blank worksheet into your incident notes. Fill in only what you observed. No signup, submission or browser storage. Do not include broker URLs, credentials, task arguments or customer details.

No reply is unknown, not proof of failure. Task success alone does not prove email delivery or payment completion. Check the original attempt and possible side effects before considering a replay.

Need the same review across client websites? Use the Django client-site maintenance checklist. Choosing tooling? Evaluate monitoring tools on the same staging scenario.

Queued or already running?

The same “slow task” symptom has two different causes

A customer can wait ten minutes for a task that runs in two seconds. Looking only at execution time would call that healthy. Store publish and start timestamps so you can tell whether the queue or the task code caused the delay.

Segment by queue and task name before scaling workers. One overloaded low-priority queue can otherwise hide inside a harmless portfolio average.

SignalLikely problemFirst check
High queue delayCapacity or routingActive workers, queue depth and prefetch
High durationTask or dependencyDatabase, network calls and payload size
Frequent retriesTransient dependencyRetry reason, backoff and idempotency
No terminal stateWorker loss or hard timeoutWorker logs, time limits and broker visibility

Prevent the next mystery

Record where every important task stops

FetchNode can observe Celery publish, start, success, failure and retry signals when the Django integration loads. That turns “the email never arrived” into a concrete queue, worker, retry or exception timeline.

Django Tasks or a generic jobPython
from fetchnode_client import capture_job

@capture_job(job_name="billing.send_invoice", queue="billing")
def send_invoice(invoice_id):
    invoice = Invoice.objects.get(pk=invoice_id)
    deliver_invoice(invoice)

Keep the task name stable. Pass identifiers rather than personal data, and make retries idempotent before automating recovery.

After the immediate fix

Stop Celery tasks from failing silently again

  1. 1. Name and route tasks consistently

    Stable names and explicit queues make release comparisons and ownership possible.

  2. 2. Record every terminal state

    Success, failure and retry must close the execution that started.

  3. 3. Baseline delay and duration

    Use per-task expectations instead of one global timeout for every queue.

  4. 4. Test failure and retry paths

    Trigger a controlled exception and confirm the alert links to useful context.

  5. 5. Add a scheduled heartbeat

    Detect silence from workers or the scheduler, not only reported exceptions.

  6. 6. Define a retry owner

    Document when manual replay is safe and who checks idempotency first.

For the rest of the production stack, audit pre-flight settings with our Django deployment checklist, review the 12-point monitoring checklist, or compare Django APM tools.

Celery troubleshooting FAQ

Common reasons tasks stay pending or never run

Why is my Celery task stuck in PENDING?

PENDING can mean waiting, but Celery also returns it when the result backend has no information for the task ID. Check publish and worker events before assuming the task is still queued.

Why is my Celery worker not picking up tasks?

Common causes are a worker consuming a different queue, an unregistered task name, a broker connection problem or all worker slots being occupied by long-running work.

How can I tell whether a Celery task is really stuck?

Treat it as potentially stalled when it reported a start but no success, failure or retry within a threshold based on its normal duration. Confirm worker state before replaying it.

Why does Celery Beat send tasks that never run?

Beat only publishes scheduled tasks. Prove that publication happened, then check the broker, target queue, routing and worker as separate stages.

Is it safe to retry a stuck Celery task?

Only after checking that the original attempt is no longer running and that the task is idempotent. Otherwise a manual retry can duplicate emails, charges or other side effects.

From evidence to action

Keep a stalled task from becoming another blind investigation.

FetchNode records instrumented job starts, failures and stalled work. Your agent can inspect the task code and available error context; broker diagnosis and safe replay still need deliberate checks.

  1. 01

    Start with the evidence.

    Choose a website and inspect the available signals, their time window and any missing context.

  2. 02

    Give your agent a specific task.

    Your coding agent can retrieve project-scoped context through MCP and work in your repository.

  3. 03

    Review, deploy and measure.

    Review the proposed changes and checks. After deployment, use new measurements to assess the result.

See how your coding agent can help

Know a background task failed before a customer reports it

Start with one production project, verify a successful task and a controlled failure, then detect jobs that fail, retry repeatedly or never report completion.