Le tueur de Celery de Django est arrivé

Django 6.0 introduit un cadre natif pour les tâches en arrière-plan, remettant directement en question la domination de longue date de Celery. Découvrez si cet nouvel outil est la solution simple et intégrée que votre projet attendait.

Hero image for: Le tueur de Celery de Django est arrivé
💡

TL;DR / Key Takeaways

Django 6.0 introduit un cadre natif pour les tâches en arrière-plan, remettant directement en question la domination de longue date de Celery. Découvrez si cet nouvel outil est la solution simple et intégrée que votre projet attendait.

L'attente de 20 ans pour les tâches natives est terminée.

Pendant presque 20 ans, les développeurs Django ont contourné une omission flagrante : il n'existe pas de manière native d'exécuter des tâches en arrière-plan. L'envoi d'emails, le traitement des téléchargements, l'analyse des rapports ou l'appel d'API tierces dépendaient d'outils tiers, Celery devenant le standard de facto dès la fin des années 2000.

Cette norme non officielle a eu un coût. Les équipes ont dû ajouter un courtier séparé, un pool de travailleurs et une pile de surveillance juste pour éviter de bloquer une seule requête HTTP, même pour des tâches triviales comme « envoyer un e-mail de bienvenue » ou « recalculer un compteur ».

La communauté se plaint de ce manque depuis plus d'une décennie dans des tickets, des articles de blog et des conférences. Ce que les gens voulaient réellement semblait simple : une API standardisée intégrée pour le travail asynchrone qui ne force pas l'utilisation de Redis, RabbitMQ ou d'une implémentation spécifique de travailleur pour chaque projet.

Au lieu de cela, l'écosystème s'est fragmenté. Certaines équipes se sont complètement engagées sur Celery ; d'autres ont choisi Huey, RQ ou des files d'attente maison. Remplacer l'une d'elles signifiait des réécritures invasives, car chaque bibliothèque incluait ses propres décorateurs, objets de résultat, et sémantiques de réessai intégrées directement dans le code de l'application.

Cette pression s'est finalement cristallisée en une proposition formelle d'amélioration de Django (Django Enhancement Proposal) de la part du contributeur principal Jake Howard. Sa proposition de cadre de tâches Django (Django Tasks DEP) propose un cadre de tâches Django minimal et modulable qui existerait dans le cœur de Django, définirait l'API publique et permettrait aux backends de rivaliser sur les détails d'implémentation.

Le design d'Howard trace une ligne nette : Django contrôlerait la manière dont vous déclarez et mettez en file d'attente les tâches, tandis que les backends tiers s'occuperaient du stockage, des travailleurs et de la mise à l'échelle. Cette séparation reflète la façon dont Django traite les bases de données ou les caches, et elle a immédiatement trouvé un écho chez les mainteneurs fatigués de coupler la logique métier à une seule bibliothèque de file d'attente.

Django 6.0, sorti en décembre 2025 après une version alpha en septembre, une bêta en octobre et une RC1 en novembre, est le véritable aboutissement de cette proposition. Le nouveau module des tâches est inclus dans le framework, et non en tant qu'extension, et chaque nouveau projet dispose désormais d'une gestion des tâches en arrière-plan de premier ordre dès le premier jour.

Sur le plan architectural, cela marque un tournant dans l'échelle des vues asynchrones de Django ou du cadre de migrations. Le travail en arrière-plan n'est plus « un système externe que vous collez ensuite », mais une capacité essentielle sur laquelle d'autres fonctionnalités, des applications tierces et de futurs DEP peuvent s'appuyer directement.

La nouvelle arme de Django : la couche API modulable

Illustration : La nouvelle arme de Django : La couche API pluggable
Illustration : La nouvelle arme de Django : La couche API pluggable

Le nouveau Framework de Tâches Django 6.0 établit une distinction claire entre la définition et l'exécution. Le cœur de Django standardise désormais la manière de déclarer une tâche et de la placer dans une file d'attente, mais refuse de dicter ce qui exécute cette file, à quoi ressemblent les travailleurs ou où les emplois sont stockés. Cette séparation transforme les tâches en une couche API interchangeable plutôt qu'en un travailleur de fond monolithique intégré à l'ORM ou à la pile de requêtes.

Au cœur du système se trouve le décorateur @task. Vous l'appliquez à une fonction ordinaire, et Django l'enregistre en tant que tâche avec des métadonnées telles que le nom de la file d'attente, la priorité et si elle nécessite un contexte de tâche. Les tâches doivent se situer au niveau du module, accepter des arguments sérialisables en JSON et retourner des valeurs, et peuvent choisir `takes_context=True` pour recevoir un objet de contexte exposant le nombre de tentatives et l'ID de `TaskResult`.

Une fois qu'une fonction devient une tâche, vous confiez le travail au cadre avec `enqueue()`. Depuis le code synchrone, vous appelez `enqueue(my_task, *args, **kwargs)` ; depuis le code asynchrone, les backends peuvent exposer `aenqueue()` pour la même API, mais avec un `await`. En coulisses, Django transmet cet appel au backend configuré, qui décide si cela signifie envoyer un message dans Redis, écrire dans Postgres, ou faire quelque chose de complètement personnalisé.

Chaque appel à `enqueue()` renvoie un objet TaskResult, l'unique abstraction de Django sur "ce qui est arrivé à ma tâche". Cet objet porte un ID unique que vous pouvez stocker dans votre base de données ou renvoyer au client, puis recharger plus tard via quelque chose comme `get_result(id)` pour inspecter des champs tels que le statut, les détails de l'erreur, les tentatives et la valeur de retour. Les utilisateurs du framework n'interagissent jamais directement avec les internals du backend ; ils communiquent avec TaskResult et laissent le backend le mapper sur son propre stockage.

L'incomplétude délibérée définit ce design. Django ne fournit pas de travailleur de production, pas de moteur de réessai, pas de planificateur de type cron, et pas d'API de chaînage ; tout cela appartient aux backends ou aux bibliothèques tierces. Le cœur ne promet que l'@task, l'enqueue() et le TaskResult restent stables afin que l'écosystème puisse construire des travailleurs, des tableaux de bord et des ponts vers Celery, RQ ou Redis en supplément.

Les backends initiaux restent intentionnellement minimaux. Le backend `immediate` exécute les tâches de manière synchrone dès que vous appelez `enqueue()`, ce qui rend les tests unitaires et le débogage local triviales, car les traces de pile et les points d'arrêt se comportent exactement comme des appels de fonctions normaux. Le backend `dummy` rejette chaque tâche sans exécuter quoi que ce soit, idéal pour les environnements où vous devez maintenir les appels de tâches en place mais ne pouvez pas permettre une exécution réelle, comme certains environnements de mise en scène ou de simulation.

La "Solution à 80%" que vous attendiez.

Le travail en arrière-plan dans Django signifie généralement les mêmes trois tâches, encore et encore : envoyer des emails, traiter les téléchargements d'utilisateurs et communiquer avec des API externes. Ce « cas d'utilisation à 80 % » n'a que rarement besoin de flux de travail étendus, de routage distribué ou de limitation de taux par file d'attente. Il a juste besoin d'arrêter de bloquer le fil de demande pendant qu'un serveur SMTP, un compartiment S3 ou un fournisseur de paiement se réveille.

Le framework de tâches Django cible directement cette bande. Vous décorez une fonction avec @task, appelez `enqueue()` (ou `aenqueue()`), et déléguez des tâches telles que « envoyer cet email de réinitialisation de mot de passe » ou « générer des miniatures pour cette image ». Pour de nombreuses applications, ce schéma unique couvre les réinitialisations de mot de passe, les séquences d'intégration, l'envoi de webhooks, la génération de PDF et le préchauffage du cache.

Historiquement, les équipes utilisaient Celery pour ces tâches et finissaient par faire fonctionner une pile complète de files d'attente pour un petit nombre de fonctions. Vous aviez un courtier, un backend de résultats, un pool de travailleurs, une planification beat, et une forêt de paramètres avant que votre premier e-mail ne quitte le bâtiment. Le cadre de tâches de Django élimine cette exigence pour les cas simples en standardisant l'API tout en restant agnostique vis-à-vis de la machinerie lourde qui se cache derrière.

Considérez cela comme une rampe d'accès : vous vous engagez à une manière de déclarer et de mettre en file des tâches, bien avant de vous engager sur RabbitMQ, Redis ou une ferme de travailleurs à l'échelle de Kubernetes. Les projets en phase de démarrage peuvent commencer avec le backend immédiat, puis échanger un véritable travailleur soutenu par une file d'attente lorsque le trafic et la latence l'exigent. Pas de refactorisation massive, pas de retrait des décorateurs spécifiques à Celery dans l'ensemble du code.

Les propres backends de Django restent intentionnellement minimalistes : un backend immédiat qui exécute les tâches en ligne, et un backend fictif qui n’exécute jamais rien. Cela maintient les dépendances faibles, donne une impression de native à Django et évite de faire appel à des démons supplémentaires pour des applications CRUD ou des outils internes. Pour des détails sur les backends, le contexte et la gestion des résultats, la documentation du framework des tâches de Django 6.0 décrit le contrat auquel se branchent les travailleurs tiers.

Anatomie d'une tâche Django moderne

Le travail en arrière-plan dans Django 6.0 commence par une simple fonction Python enveloppée dans le nouveau @task décorateur. Un exemple minimal ressemble à ceci :

```python from django.tâches import tâche, mettre_en_attente, amettre_en_attente, obtenir_résultat ```

@tâche( priorité=5, nom_de_file="notifications", prend_contexte=True, ) def notifier_utilisateur(contexte_tâche, id_utilisateur, message): """ Envoyer une notification à un utilisateur.

# Accéder aux métadonnées concernant cette tentative d'exécution spécifique = task_context.attempt # 1 lors de la première tentative, s'incrémente lors des réessais result_id = task_context.task_result_id # ID stable pour le suivi

# Votre logique réelle se trouve ici (email, push, SMS, etc.) # Vous pouvez enregistrer la tentative/result_id pour l'observabilité return {"status": "envoyé", "tentative": tentative, "result_id": result_id}

Ces arguments de décorateur sont les principaux paramètres que Django expose. priority est un indice numérique pour le backend ; des chiffres plus élevés signifient « s'exécuter plus tôt » par rapport à d'autres tâches dans la même file d'attente. queue_name achemine le travail vers une file d'attente spécifique comme « notifications » ou « traitement d'images », tandis que `takes_context=True` injecte un objet task_context comme premier paramètre.

`task_context` transforme une fonction à exécution instantanée en quelque chose que vous pouvez réellement observer. `task_context.attempt` expose combien de fois cette tâche a été exécutée jusqu'à présent, ce qui devient essentiel une fois que votre backend ajoute des tentatives supplémentaires. `task_context.task_result_id` vous fournit un identifiant stable que vous pouvez stocker dans votre base de données, vos journaux ou vos analyses, afin de pouvoir vous reconnecter à cette exécution ultérieurement.

L'enregistrement de travaux utilise l'aide enqueue() pour le code synchronisé. Depuis une vue ou un gestionnaire de signaux, vous pourriez faire :

```python def creer_commande( demande ): # ... créer une commande, valider la transaction ... resultat = mettre_en_file( notifier_utilisateur, user_id=demande.utilisateur.id, message="Votre commande est en route!", ) # resultat.id == identifiant_resultat_tache return JsonResponse({"identifiant_tache": resultat.id}) ```

Le code asynchrone utilise `aenqueue()` à la place, reflétant ainsi les vues asynchrones et les consommateurs de Django :

```python async def async_view(request): result = await aenqueue(notify_user, user_id=1, message="Salut") return JsonResponse({"task_id": result.id}) ```

Une fois que vous avez un `task_result_id`, les vérifications de statut s'effectuent via `get_result()`:

```python from django.http import JsonResponse from django.views.decorators.http import require_GET ```

@require_GET def task_status(request, task_id): result = get_result(task_id) return JsonResponse( { "id": result.id, "status": result.status, # par exemple "en attente", "en cours", "terminé", "échec" "attempts": result.attempts, # tentatives totales jusqu'à présent "value": result.value, # valeur de retour de notify_user, si terminé "error": result.error, # informations d'erreur spécifiques au backend, si échec } )

Ce trio — `@task`, `enqueue()`/`aenqueue()`, et `get_result()` — constitue la surface minimale et standardisée que chaque backend du Framework de Tâches Django doit respecter.

Les pièces manquantes : Ce que Django laisse de côté

Illustration : Les pièces manquantes : Ce que Django laisse de côté
Illustration : Les pièces manquantes : Ce que Django laisse de côté

Pas de surprise ici : Django 6.0 ne propose aucun worker intégré. Vous pouvez définir et mettre en file d'attente des tâches avec le Django Tasks Framework, mais les configurations en production ont toujours besoin d'un processus séparé et de longue durée pour tirer des tâches d'un backend et les exécuter. La documentation officielle et les premières discussions insistent sur ce point : un « worker de tâches Django » ou équivalent est obligatoire dès que vous quittez le shell de développement.

L'API principale de Django ignore également les commodités que les utilisateurs de Celery tiennent pour acquises. Il n'y a pas de support de première partie pour les réessais automatiques lorsqu'un fournisseur d'emails rencontre un délai d'attente, pas de calendriers intégrés de style cron, et pas de chaînes ou de groupes de tâches natifs. Si vous souhaitez "exécuter ceci toutes les 5 minutes" ou "démarrer la tâche C uniquement après que A et B ont réussi", vous ne trouverez pas cette logique dans django.tasks.

Ces fonctionnalités résident entièrement dans le backend que vous ajoutez. Un worker basé sur Redis, un pont RQ ou un futur adaptateur Celery peuvent décider comment mettre en œuvre des tentatives, des stratégies de rétrogradage, des tâches périodiques et des pipelines de diffusion/rassemblement. Django ne promet qu'une surface stable : `@task`, des appels d'ajout en file d'attente et une abstraction TaskResult que les backends peuvent étendre.

Les concepteurs du cadre de tâches Django ont rendu cette contrainte explicite dès le premier jour. Le noyau de Django propose uniquement un backend immédiat (exécute les tâches en ligne) et un backend factice (ne les exécute jamais), tous deux intentionnellement non destinés à la production. Tout ce qui persiste réellement des travaux, coordonne des travailleurs ou gère une exécution distribuée provient de packages tiers.

Cette séparation crée une ligne de responsabilité nette. Django possède l'interface : comment vous déclarez des tâches, comment vous passez des arguments, comment vous inspectez les résultats. La communauté possède l'implémentation : comment les tâches sont sérialisées, où elles sont mises en file d'attente, comment les travailleurs se répartissent sur des conteneurs ou des régions.

Pour les équipes habituées à Celery, cela ressemble presque à du matériel nu. Vous gagnez un point d'entrée standardisé, approuvé par le cadre, mais vous perdez le planificateur, l'inspecteur et l'orchestration de réessai inclus jusqu'à ce que votre backend choisi les réintroduise. Les premières expériences visent déjà Redis, RQ, et même Celery lui-même comme backends qui parlent l'API du Django Tasks Framework.

À long terme, cela reflète le modèle existant de Django : ORM, cache et couches d'email définissent des contrats, tandis que Postgres, Redis et les serveurs SMTP font le gros du travail. Les tâches s'ajoutent maintenant à cette liste, intentionnellement, de manière incomplète.

Le royaume de Céleri sous siège ?

Celery a construit son empire sur une seule promesse : des tâches en arrière-plan de niveau industriel pour Django bien avant que Django ne s'en soucie. Maintenant, Django 6.0 propose un Cadre de Tâches Django qui intègre les déclarations de tâches dans le noyau, et soudain, Celery n'est plus l'hypothèse par défaut, mais simplement le plus grand acteur sur le terrain.

Côte à côte, les modèles semblent très différents. Django Tasks définit une API standard : `@task`, fonctions d'enfilement et objets `TaskResult`, tout en déléguant le stockage et l'exécution à des backends modulaires. Celery propose une solution complète : courtier, travailleurs, planificateurs, stockages de résultats et une décennie d'outils dans l'écosystème.

Une comparaison rapide rend la séparation évidente :

  • 1Tâches Django : partie de Django, configuration minimale, charges utiles en JSON uniquement, backends nécessaires pour de vraies files d'attente
  • 2Céléri : paquet séparé, nécessite un courtier comme Redis ou RabbitMQ, prend en charge la sérialisation complexe, inclut des travailleurs et un planificateur beat
  • 3Django Tasks : idéal pour les emails, les uploads, les appels API et les hooks sur commit
  • 4Celery : optimisé pour les clusters distribués, le haut débit et les architectures multi-services.

Celery domine toujours là où l'échelle et la complexité comptent. Vous bénéficiez de reprises intégrées avec un backoff exponentiel, de tâches périodiques via beat, et de primitives de flux de travail comme les chaînes, les groupes et les accords qui orchestrent des dizaines de tâches à travers de nombreux travailleurs. Les grandes déploiements traitent régulièrement des milliers de tâches par seconde via Celery soutenu par Redis ou RabbitMQ.

Django Tasks met l'accent sur l'ergonomie. Vous restez à l'intérieur de Django, importez depuis `django.tasks`, décorez une fonction et appelez `enqueue()` sans toucher directement à un broker. Pour environ "80% des cas d'utilisation" — emails transactionnels, génération de vignettes, réchauffeurs de cache, fan‑outs de webhook — ce sentiment de zéro dépendance à l'intérieur de Django élimine une barrière majeure à l'adoption.

Les utilisateurs avancés perdent certaines fonctionnalités s'ils abandonnent Celery aujourd'hui. Pas de travailleur officiel, pas de politiques de réessai natives, pas de planification intégrée et pas d'interface utilisateur de surveillance éprouvée avec Django 6.0. Ces éléments résident dans des backends communautaires et des tableaux de bord tiers, qui sont toujours en retard par rapport à l'écosystème bien établi de Celery.

De manière stratégique, Django Tasks modifie la question par défaut que se posent les équipes. Les nouveaux projets commenceront avec le cadre de base et n’utiliseront Celery que lorsque les exigences nécessiteront clairement des flux de travail distribués, un routage avancé ou des SLA stricts. Celery devient un chemin d’escalade, et non un point de départ.

Alors, Django 6.0 tue-t-il Celery ? Non — cela limite le territoire de Celery. Les tâches en arrière-plan appartiennent désormais par défaut à Django, tandis que Celery défend le secteur haut de gamme, multi-nœuds, de « jamais laisser tomber une tâche ». Pour des détails techniques plus approfondis, les notes de version de Django 6.0 expliquent exactement comment le nouveau Cadre de Tâches Django s'intègre dans de véritables backends.

Quand vous avez vraiment besoin de céleri

Celery reste la meilleure option quand votre travail en arrière-plan ne ressemble plus à une quête secondaire et commence à se comporter comme un système distribué à part entière. Lorsque vous avez besoin de centaines de travailleurs, de multiples files d'attente réparties sur plusieurs régions, et d'un comportement prévisible lors de pics de plus de 10 000 emplois par seconde, les cicatrices de guerre de plus de dix ans de Celery importent bien plus que le nouvel éclat de Django.

Utilisez Celery lorsque vous avez besoin d'une logique de routage avancée au lieu d'un mode "fire-and-forget". Cela signifie des fonctionnalités telles que : - Plusieurs files d'attente par service avec des clés de routage granulaires - Limitation de taux par tâche et plafonnement de la concurrence - Limites de temps strictes et souples, et comportement automatique de disjoncteur

Les workflows sérieux s'appuient toujours sur le support AMQP de Celery et la flexibilité des brokers. Si votre architecture fonctionne déjà avec RabbitMQ, Redis, ou même des brokers plus exotiques, vous bénéficiez de files d'attente durables, d'accusés de réception de messages, d'échanges de lettres mortes et de sémantiques de rétroaction qui ne sont pas définies intentionnellement par le Framework de Tâches Django.

Les pipelines complexes vous renvoient également à Celery. Les accords, groupes, chaînes et toiles vous permettent d'orchestrer des tâches de fan‑out/fan‑in, des pipelines ETL en plusieurs étapes et des charges de travail en science des données de longue durée pouvant s'étendre sur des dizaines de tâches et de machines. L'API de tâches de Django peut mettre des travaux en file d'attente, mais elle ne modélise pas ce type de graphique de flux de travail.

La surveillance est une autre ligne de démarcation. Les équipes qui utilisent Flower, les tableaux de bord Prometheus et les tableaux personnalisés Grafana basés sur le flux d'événements de Celery n'accepteront pas "vérifiez le TaskResult" comme alternative. Celery expose des métriques par travailleur, les profondeurs de file d'attente, les tempêtes de réessai et les histogrammes de latence des tâches que les SRE utilisent pour maintenir les SLA intacts.

Les plateformes SaaS à fort volume, les backends fintech et les places de marché traitant des millions de tâches par jour considèrent toujours Celery comme une infrastructure essentielle. Pour ce niveau, les sémantiques de nouvelle tentative éprouvées de Celery, ses backends de résultats et ses outils opérationnels demeurent inégalés par la couche modulaire jeune de Django.

L'Écosystème s'éveille

Illustration : L'Écosystème S'éveille
Illustration : L'Écosystème S'éveille

Des ondes de choc ont frappé le territoire Django presque immédiatement après la fusion du Django Tasks Framework. Quelques jours après les versions candidates 6.0, des référentiels communautaires ont commencé à apparaître avec des backends Redis "expérimentaux", des exécuteurs de tâches et des intégrations administratives cherchant à transformer l'API brute en quelque chose que l'on peut réellement déployer en production.

Les premiers adopteurs ont ciblé le fossé évident : un worker prêt à la production qui parle la nouvelle interface. Des paquets sont apparus, enveloppant les listes ou flux Redis, faisant surgir une commande de gestion `worker`, et mappant `priority` et `queue_name` depuis `@task` directement sur les structures de données Redis, recréant ainsi efficacement un exécuteur léger de style RQ derrière le Django Tasks Framework.

Redis est rapidement devenu le terrain de jeu par défaut. Une famille d'adaptateurs se concentre sur des configurations ultra simples : une seule instance Redis, des files d'attente FIFO, pas de sharding, optimisées pour ce « cas d'utilisation à 80 % » d'emails, de traitement d'images et d'appels webhook. Une autre vague expérimente des fonctionnalités plus avancées comme les jobs retardés, les tentatives de réessai basées sur le backoff et les limites de taux par file d'attente, le tout exposé via de simples kwargs de décorateur.

Les packages de pont visent désormais à connecter les écosystèmes existants plutôt qu'à les remplacer. Vous pouvez déjà trouver des prototypes qui vous permettent de réutiliser des URL de courtier de style Celery tout en routant toutes les définitions de tâches via `@task`, de sorte que votre code semble natif mais que votre infrastructure repose toujours sur les travailleurs robustes et les outils de surveillance de Celery.

Les croquis les plus ambitieux sont ceux d'un "backend Celery" qui permettrait à Celery de fonctionner comme un travailleur directement intégré derrière l'API de tâches standard de Django. L'idée : les tâches restent natives au framework, mais un adaptateur backend traduit les appels `enqueue()` en tâches Celery, mappe les IDs de résultats et proxi les vérifications de statut, afin que vous puissiez migrer de manière incrémentale au lieu de réécrire des années de code de tâches.

Les discussions sur la liste de diffusion de Django, les problèmes GitHub et les fils Twitter tournent autour de trois piliers manquants : l'observabilité, les hooks de cycle de vie et une expérience utilisateur admin améliorée. Les gens souhaitent des événements structurés pour « tâche commencée / réessayée / échouée », des backends de surveillance modulables qui peuvent diffuser ces événements vers des outils comme Better Stack, et des tableaux de bord de première classe qui montrent les files d'attente, les travailleurs et les chemins critiques directement dans l'admin de Django.

Si le modèle se maintient, attendez-vous à un écosystème darwinien au cours des 6 à 12 prochains mois : une demi-douzaine de workers Redis, au moins un pont Celery, et quelques distributions "prêtes à l'emploi" avec des opinions bien arrêtées qui se batailleront pour devenir le standard de facto en tant que backend pour les tâches de Django 6.0.

Obstacles pratiques et pièges à éviter

JSON est en tête. Les tâches Django sérialisent les arguments et les valeurs de retour en utilisant JSON, ce qui signifie que tout ce que vous passez à une tâche doit être compatible avec JSON : chaînes, nombres, booléens, listes, dictionnaires. Si vous lui donnez un `datetime`, un `Decimal` ou une instance de modèle, vous obtiendrez des erreurs de sérialisation ou une perte silencieuse une fois que les backends commenceront à appliquer des types stricts.

Vous pouvez contourner cela, mais vous devez être explicite. Convertissez les objets complexes en représentations primitives (ID, chaînes ISO 8601, dictionnaires simples) et reconstruisez-les à l'intérieur de la tâche. Une bonne règle : si cela ne peut pas survivre à un aller-retour `json.dumps()` / `json.loads()`, ne l'envoyez pas comme argument de tâche ou valeur de retour.

Les écritures dans la base de données introduisent une autre difficulté. Si vous placez une tâche dans la file d'attente pendant une vue qui s'exécute à l'intérieur de `transaction.atomic()`, la tâche pourrait s'exécuter avant que la transaction ne soit validée, voir des données obsolètes ou échouer en raison de lignes manquantes. Le crochet on_commit de Django existe précisément pour éviter cette concurrence.

Modèle à retenir : effectuez l'écriture, puis planifiez la tâche depuis `on_commit`. Par exemple, après avoir créé une `Commande`, utilisez `transaction.on_commit(lambda: send_order_email.enqueue(order_id=order.id))` afin que le travailleur ne voie que l'état engagé. Ne pas le faire créera des heisenbugs qui n'apparaissent que sous charge ou avec des bases de données lentes.

Les travailleurs vivent encore en dehors de votre processus principal. Vous devez exécuter un processus worker dédié (ou plusieurs) sous quelque chose comme systemd, Supervisor ou Kubernetes Jobs. Cela signifie des manifestes de déploiement supplémentaires, des vérifications de santé, des journaux et des politiques de redémarrage, tout comme vous le faites déjà pour Celery.

Opérationnellement, cette nouvelle pile réduit les dépendances mais pas les responsabilités. Vous devez toujours réfléchir aux limites de concurrence, à la pression sur les files d'attente et aux arrêts gracieux pour que les tâches puissent se terminer avant que les processus ne s'arrêtent. Pour de nombreuses équipes, il s'agit d'une nouvelle couche opérationnelle, et non d'une fonctionnalité gratuite.

Surveiller les terrains dans la catégorie "un peu d'assemblage requis". Celery a Flower, des exportateurs Prometheus et des années de tableaux de bord ; Django Tasks n'en fournit aucun. Les premiers backends exposent un état de base via `TaskResult`, mais vous allez probablement d'abord connecter des vues administratives personnalisées, des logs ou une intégration APM.

L'exploration au niveau du code source sera utile. Le code source du cadre de tâches Django montre exactement comment les résultats, les statuts et les erreurs circulent, sur quoi vous vous appuierez en attendant que des interfaces utilisateur tierces plus riches et des métriques les rejoignent.

Votre prochaine étape avec les tâches Django

Les projets Django existants doivent considérer le Django Tasks Framework comme une mise à niveau incrémentale et non comme une migration à jour fixe. Si vous exécutez déjà Celery, RQ ou Huey en production et qu'ils fonctionnent, conservez-les pour les chemins critiques et introduisez Django Tasks uniquement pour de nouveaux flux à faible risque. Les réécritures complètes de configurations complexes de Celery ne sont que rarement rentables dans la version 1 d'une nouvelle API.

Les nouveaux projets démarrant sur Django 6.0 peuvent en toute sécurité s'appuyer sur Django Tasks pour les tâches "80 %" : emails, génération de vignettes, préchauffage de cache et appels simples d'API tierces. N'envisagez Celery que lorsque vous savez avoir besoin de flux de travaux interservices, de jobs programmés à grande échelle ou de milliers de tâches par seconde à travers plusieurs files d'attente.

Les équipes bloquées sur Django 5 peuvent encore expérimenter aujourd'hui en utilisant le backport officiel. Installez le package de backport, intégrez-le dans `INSTALLED_APPS`, et configurez le backend immédiat ou factice afin d'éviter de devoir mettre en place Redis ou RabbitMQ dès le premier jour. Vous bénéficiez du même décorateur `@task` et de l'API `enqueue()` que dans Django 6.0 sans avoir à effectuer une mise à niveau généralisée du framework.

L'expérimentation sécurisée consiste à choisir une fonctionnalité non critique et à la transférer vers Django Tasks derrière un drapeau de fonctionnalité. Les candidats idéaux incluent :

  • 1E-mails de réinitialisation de mot de passe ou de confirmation d'inscription.
  • 2« Merci de vous être inscrit » ou « Nous avons reçu votre commande »
  • 3Webhooks à faible volume vers des services d'analyse ou de journalisation

Commencez par déplacer un seul e-mail de réinitialisation de mot de passe vers une tâche en arrière-plan qui utilise `on_commit()` pour être mise en file d'attente après la sauvegarde du modèle utilisateur. Utilisez le backend immédiat en développement, puis passez à un simple backend Redis et à un seul processus de travail en pré-production. Mesurez la latence des requêtes et les taux d'échec des tâches avant de toucher à quoi que ce soit qui soit adjacent aux revenus.

Traitez la sérialisation JSON uniquement comme une fonction de contrainte plutôt que comme une limitation : refactorisez les arguments de tâche en ID et en primitives au lieu de passer des instances de modèle complètes. Cette discipline facilite le passage entre Celery, un backend Redis, ou tout futur adaptateur Django Tasks Framework.

Stratégiquement, Django Tasks marque un point de maturité pour Django en tant que framework web tout-en-un. Le travail en arrière-plan utilise désormais une API commune et essentielle, ce qui réduit la surcharge de dépendance et rend Django plus compétitif et autonome pour la majorité des applications web qui n'ont pas besoin d'une orchestration Celery de niveau industriel.

Questions Fréquemment Posées

Qu'est-ce que le nouveau framework Django Tasks ?

C'est une API intégrée dans Django 6.0 pour définir et mettre en file d'attente des tâches en arrière-plan. Elle standardise la création des tâches mais nécessite un backend et un processus de travail distincts pour leur exécution.

Django 6.0 remplace-t-il complètement Celery ?

Non. Le cadre est conçu pour des cas d'utilisation plus simples et courants (la « solution à 80 % ») comme l'envoi d'e-mails. Pour des flux de travail complexes et distribués avec des tentatives intégrées et des chaînes, Celery reste l'outil le plus puissant.

Le cadre de tâches Django comprend-il un agent ?

Non, cela ne le fait pas. C'est intentionnel pour garder le cœur de Django léger. Vous devez configurer un backend tiers et exécuter un processus de travail séparé pour exécuter les tâches.

Puis-je utiliser la nouvelle API des tâches avec les anciennes versions de Django ?

Oui, une bibliothèque de backport vous permet d'utiliser la nouvelle API des tâches avec Django 5, facilitant ainsi l'expérimentation et la préparation à la migration vers Django 6.0.

Frequently Asked Questions

Le royaume de Céleri sous siège ?
Celery a construit son empire sur une seule promesse : des tâches en arrière-plan de niveau industriel pour Django bien avant que Django ne s'en soucie. Maintenant, Django 6.0 propose un Cadre de Tâches Django qui intègre les déclarations de tâches dans le noyau, et soudain, Celery n'est plus l'hypothèse par défaut, mais simplement le plus grand acteur sur le terrain.
Qu'est-ce que le nouveau framework Django Tasks ?
C'est une API intégrée dans Django 6.0 pour définir et mettre en file d'attente des tâches en arrière-plan. Elle standardise la création des tâches mais nécessite un backend et un processus de travail distincts pour leur exécution.
Django 6.0 remplace-t-il complètement Celery ?
Non. Le cadre est conçu pour des cas d'utilisation plus simples et courants comme l'envoi d'e-mails. Pour des flux de travail complexes et distribués avec des tentatives intégrées et des chaînes, Celery reste l'outil le plus puissant.
Le cadre de tâches Django comprend-il un agent ?
Non, cela ne le fait pas. C'est intentionnel pour garder le cœur de Django léger. Vous devez configurer un backend tiers et exécuter un processus de travail séparé pour exécuter les tâches.
Puis-je utiliser la nouvelle API des tâches avec les anciennes versions de Django ?
Oui, une bibliothèque de backport vous permet d'utiliser la nouvelle API des tâches avec Django 5, facilitant ainsi l'expérimentation et la préparation à la migration vers Django 6.0.
🚀Discover More

Stay Ahead of the AI Curve

Discover the best AI tools, agents, and MCP servers curated by Stork.AI. Find the right solutions to supercharge your workflow.

Back to all posts