Django 6.0 adds a built-in Tasks framework, a first-party way to define background work with a @task decorator and an .enqueue() method, so you can offload jobs like sending email without reaching for Celery on day one. The twist that has the community arguing: Django defines what a task is, but it does not ship a production worker to run one. That is a feature, not an oversight, and it tells you exactly how the core team thinks about scope.

  • Django 6.0 shipped December 3, 2025, the framework's 20th-anniversary release, supporting Python 3.12, 3.13, and 3.14.
  • The new django.tasks module adds a @task decorator and .enqueue() to move work out of the HTTP request-response cycle without a third-party package.
  • It ships only two backends, ImmediateBackend (runs synchronously) and DummyBackend (never runs), both meant for development and testing, not production.
  • The release also lands native Content Security Policy support, template partials, and Python's modern email API.
How Django 6.0 tasks move work off the request A web request calls a view, which enqueues a task and returns immediately, while a separate worker process you provide picks the task off a backend and runs it. HTTP requestView.enqueue()Worker you provide fast response returns before the task runs Backend (queue) : ships as dev-only genztech.blog
Fig 1 The view enqueues and returns fast. Django owns the left side of this diagram now, the task and the backend contract, but the worker on the right is still yours to run.

What does the Tasks framework actually give you?

A shared vocabulary. Before 6.0, "background job" in Django meant bolting on Celery, RQ, or a homegrown thread pool, each with its own way of defining, queuing, and reporting on work. The new django.tasks module standardizes that: decorate a function with @task, call email_users.enqueue(...), and Django handles task definition, argument validation, queuing against a configured backend, and result objects in a consistent, first-party way. That consistency is the real deliverable. A library author writing a worker now targets one official interface instead of inventing another. For simple needs, sending a confirmation email, updating a search index, firing a webhook, you can write the task once and swap the execution engine underneath it later without rewriting your application code.

RelatedPostgreSQL 19 Beta Makes Async I/O Actually Scale

Why did Django refuse to ship a worker?

On purpose, and it is the most contested decision in the release. Out of the box you get ImmediateBackend, which runs the task synchronously the instant you enqueue it, so a five-second job means a five-second response, and DummyBackend, which accepts tasks and runs nothing. Both are explicitly for development and testing. The core team declined to ship a database-backed production worker because execution infrastructure varies wildly between projects, and freezing one choice into the framework would repeat mistakes other frameworks made. So Django defines what a task is, what a result looks like, and how a backend must behave, then hands execution to the ecosystem. Purists call it elegant. Pragmatists call it a footgun for anyone who reads "built-in background tasks" and assumes something production-ready arrives configured. Both are right.

OptionDjango 6 TasksCelerydjango-tasks-local
Production workerNot includedYes, matureThread pool
Scheduling / recurrenceNoYes (beat)No
Retries, backoffNoYesNo
PersistenceBackend-definedDurable (broker)In-memory only
Best forFirst-party interfaceComplex pipelinesFire-and-forget, no infra

Is this a Celery killer?

No, and it is not trying to be. The consensus among early reviewers is that Tasks targets the shallow end: asynchronous emails, small file processing, search-index updates, webhook callbacks, and MVPs that should not haul in Redis and a broker just to send a welcome email. Celery still owns the deep end, periodic and scheduled jobs, task chains and workflows, guaranteed delivery with durable persistence, distributed workers, and retry policies with exponential backoff. Django's system, by design, has no scheduling, no recurrence, no retries, and no durable guarantees. For production today the community fills the gap: the third-party django-tasks package adds a database-backed worker, while django-tasks-local runs jobs in a ThreadPoolExecutor with the honest caveat that results live in memory and vanish on restart. Choose based on how much you would miss a job that silently disappears.

What to watch · 2026
  • Which backend wins. The value of a standard interface depends on a great third-party worker becoming the default. Watch adoption of django-tasks and friends.
  • The "it's built in" trap. Teams that ship ImmediateBackend to production will learn the hard way that enqueue blocked the request. Docs and defaults matter here.
  • Scheduling. No recurrence is the biggest gap. Whether the framework grows one, or leaves it to Celery, shapes how far Tasks reaches.
  • CSP uptake. Native Content Security Policy is the sleeper feature of 6.0 and a real security win if teams actually turn it on.

Our take

Django 6.0's Tasks framework is best understood as an abstraction, not a queue, and judged that way it is a clean, overdue piece of design. For twenty years Django had no first-party language for "run this later," and that vacuum spawned a dozen incompatible answers. Giving the ecosystem one interface to build against is the correct, patient move, exactly the kind of decision that ages well even when it frustrates people at launch. The risk is purely one of expectations: the phrase "built-in background tasks" promises more than the release delivers, and some teams will ship the synchronous dev backend straight into production and get burned. Read the release for what it is, a standard with hooks, not a batteries-included worker, and it is one of the most sensible things Django has done in years. Just do not deploy it without bringing your own engine.

Primary sources

Original analysis by GenZTech. Details per the Django 6.0 release notes, current as of July 2026. Source.