Login to manage your account

Please enter a valid email address.
Forgot Password?
Please enter a valid password.
OR

Don't have an account yet? Sign up

How do you handle background or long-running tasks in Django?

Never do them in the request-response cycle. Sending an email, generating a report, or calling a slow third-party API inside a view holds a worker process hostage and eventually times out for the user.

The standard answer is Celery with a broker such as Redis or RabbitMQ:

@shared_task(bind=True, max_retries=3)
def send_invoice(self, order_id):
    order = Order.objects.get(pk=order_id)
    try:
        mailer.send(order.email, render_invoice(order))
    except TransientError as exc:
        raise self.retry(exc=exc, countdown=60)

The view calls send_invoice.delay(order.id) and returns immediately.

The practices that matter:

  • Pass ids, not objects. Serialising a model instance means the worker acts on a stale copy.
  • Make tasks idempotent. A task can be delivered twice; running it twice must not send two invoices.
  • Set retries with backoff, and a time limit, so a hung task does not occupy a worker forever.
  • Dispatch after the transaction commitstransaction.on_commit(lambda: task.delay(id)) — or the worker may look up a row that has not been written yet. This is a classic race that is hard to reproduce.

Note: For simpler needs, mention django-q or a management command run by cron. Celery is powerful but it is real operational overhead.

All Django interview questions

Login to manage your account

Please enter a valid email address.
Forgot Password?
Please enter a valid password.
OR

Don't have an account yet? Sign up as