06 sept. 2025·8 min de lecture

Détection des tâches bloquées : signaux de vie, délais et alertes

Apprenez à détecter les tâches bloquées avec des signaux de vie simples, des délais raisonnables et des alertes claires pour savoir si le travail est lent, en erreur ou réellement bloqué.

Détection des tâches bloquées : signaux de vie, délais et alertes

Pourquoi « ça ne fonctionne pas » est si difficile à déboguer

Quand quelqu'un dit « ça ne fonctionne pas », il veut généralement dire « j'ai cliqué sur le bouton et rien ne s'est passé. » Le problème, c'est que la plupart des applis effectuent beaucoup de travail après le clic, hors de vue. Sans signaux clairs, vous ne pouvez pas dire si le travail n'a pas démarré, a démarré mais est juste lent, ou a démarré puis s'est bloqué en cours de route.

Un job en arrière-plan est simplement une tâche que votre app exécute plus tard, sans forcer l'utilisateur à attendre à l'écran. Exemples courants : générer un PDF, importer un CSV, envoyer des e-mails, construire un rapport, ou synchroniser des données. L'utilisateur déclenche, puis l'app confie le travail à un worker qui tourne en arrière-plan.

Depuis l'extérieur, trois résultats différents peuvent paraître exactement identiques :

  • Lent : il tourne, mais prend plus de temps que prévu.
  • Échoué : il s'est arrêté avec une erreur et ne finira pas tout seul.
  • Bloqué : il a démarré, mais ne progresse plus.

Les trois donnent l'impression que « rien ne se passe ». Votre dashboard peut rester affiché « queued » ou « processing » pendant des heures. Les messages au support s'accumulent. Les fondateurs finissent par deviner : le serveur est-il en panne, est-ce que ça finira demain matin, l'utilisateur a-t-il fait quelque chose de travers ?

La détection des tâches bloquées transforme ces suppositions en réponse claire. Vous voulez un moyen simple de voir :

  • Le job a-t-il démarré ?
  • Est-il toujours vivant maintenant ?
  • Quand a-t-il progressé pour la dernière fois ?
  • Quand le déclarons-nous en timeout ?
  • Qui reçoit l'alerte et que doit-il faire ensuite ?

Une fois ces questions visibles, « ça ne fonctionne pas » devient un problème diagnostiquable, pas un mystère.

Lent vs échoué vs bloqué : une définition simple

Quand quelqu'un dit « le job ne tourne pas », il veut généralement dire une des trois choses. Si vous ne nommez pas laquelle, les équipes devinent, relancent, et créent du travail en double (y compris facturer deux fois un client ou envoyer le même e‑mail deux fois).

Lent

Un job lent progresse toujours. Il peut uploader des fichiers, appeler une API, ou traiter des enregistrements, juste plus lentement que prévu. Le signal clé est que quelque chose change : les horodatages s'actualisent, les compteurs augmentent, ou de nouvelles lignes de log apparaissent.

Échoué

Un job échoué s'est arrêté. Il ne se terminera pas tout seul. Il a pu planter, rencontrer une erreur bloquante, ou perdre l'accès à une ressource nécessaire (permission, fichier manquant). L'essentiel : il est terminé, et il faut corriger la cause puis relancer pour finir le travail.

Bloqué

Un job bloqué est le plus délicat. Le job « existe » (il est en file ou marqué comme running), mais il ne progresse plus. Il est suffisamment vivant pour bloquer d'autres travaux, mais pas assez sain pour se terminer.

En pratique :

  • Lent : la progression continue de changer, même faiblement.
  • Échoué : il se termine avec une erreur et s'arrête.
  • Bloqué : il semble en cours, mais rien ne change pendant trop longtemps.

Exemple : votre e‑mail de rapport quotidien n'est pas parti. Si vous relancez aveuglément, vous risquez d'envoyer deux fois plus tard. Si vous savez qu'il a échoué, vous pouvez relancer en sécurité. Si vous savez qu'il est bloqué, vous pouvez le redémarrer volontairement au lieu d'attendre des heures.

Les trois briques de base : heartbeats, timeouts, alertes

Si vous voulez que la détection des tâches bloquées paraisse simple, imaginez‑la comme le suivi d'une livraison. Il vous faut la preuve qu'elle bouge, un point où vous décidez que ce n'est plus acceptable, et un moyen d'en informer quelqu'un.

1) Heartbeats : preuve de vie (ou de progression)

Un heartbeat est un petit signal qu'envoie un job pendant son exécution. Il peut être aussi basique que « toujours en cours » toutes les minutes, ou mieux, « 3 sur 20 items traités ». Le but n'est pas le détail, mais la confiance que le job avance.

De bons heartbeats sont réguliers et peu coûteux. Un export de fichier peut envoyer un heartbeat après chaque portion écrite. Une synchro de données peut le faire après chaque client mis à jour. Si un job ne peut pas rapporter une progression significative, il devrait au moins rapporter « je suis vivant » à intervalle régulier.

2) Timeouts : quand « peut‑être lent » devient « bloqué »

Un timeout est la règle qui transforme le silence en état clair. Il répond à la question : combien de temps êtes‑vous prêt à attendre sans heartbeat avant de considérer le job comme bloqué ?

Un réglage simple ressemble à ça :

  • Choisissez un intervalle de heartbeat attendu (par exemple, toutes les 60 secondes).
  • Autorisez une fenêtre de grâce (par exemple, 5 heartbeats manqués).
  • Marquez le job comme bloqué lorsque la fenêtre est dépassée.
  • Enregistrez la dernière progression connue pour savoir où il s'est arrêté.

3) Alertes : un message sur lequel un humain peut agir

Une alerte doit atteindre une vraie personne et contenir assez de contexte pour répondre sans deviner : quel job, quel client, quand il a progressé pour la dernière fois, et ce que le système a fait ensuite (retry, mis en pause, ou failed).

Vous n'avez pas besoin d'un dashboard sophistiqué. Une vue de statut simple suffit : dernière exécution, dernier heartbeat, et si un timeout a été déclenché. C'est ce qui transforme « ça ne fonctionne pas » en un problème observable plutôt qu'en débat.

Comment ajouter des heartbeats sans sur‑ingénierie

Un heartbeat est juste un petit signal « je suis encore là » que votre job met à jour pendant son exécution. Cela transforme la détection des tâches bloquées d'une supposition en un fait vérifiable : quand le job a‑t‑il rapporté sa dernière progression ?

Commencez par le plus petit signal de progression que vous pouvez mettre à jour en toute sécurité. Pour la plupart des équipes, une seule ligne dans une table de base est suffisante. Maintenez‑la simple et durable pour qu'un redémarrage ne l'efface pas.

Choisissez un heartbeat difficile à fausser

Choisissez un champ qui correspond à ce que « progrès » signifie pour le job :

  • last_heartbeat_at (timestamp)
  • current_step (par exemple : "fetching data", "writing file", "sending email")
  • processed_count (combien d'items ont été traités)

Mettez à jour le heartbeat seulement après avoir terminé une vraie unité de travail (une page récupérée, un lot écrit, une facture traitée). Ainsi il reflète un vrai mouvement, pas une boucle qui tourne sans fin.

Définissez un rythme d'updates adapté au job

Un heartbeat trop fréquent crée du bruit. Trop rare, et vous le découvrez trop tard.

À titre indicatif : mettez à jour après chaque étape pour les jobs courts, toutes les 1 à 5 minutes pour les jobs longs, et après chaque appel externe pour tout ce qui dépend d'une API, d'un upload ou d'un service tiers.

Rendez‑le visible. Une petite vue admin suffit : ID du job, statut, étape courante, et dernier heartbeat. Alors « ça ne fonctionne pas » devient « le dernier heartbeat était à 14h14 pendant l'étape 3. »

Choisir des timeouts qui correspondent à la réalité

Un timeout ne doit pas être un nombre au hasard. C'est une promesse : « si ce job n'a pas progressé d'ici X, quelque chose cloche probablement, et nous répondrons de façon prévisible. »

Commencez avec deux timeouts, pas un seul :

  • Un soft timeout : « c'est plus long que d'habitude »
  • Un hard timeout : « arrêtez d'attendre, quelque chose ne va pas »

Basez vos valeurs sur des exécutions réelles, pas des suppositions. Regardez votre run normal le plus lent (pas le meilleur jour, pas un incident complet) et utilisez‑le comme point de départ. Si les rapports finissent habituellement en 2 à 4 minutes mais prennent parfois 8, un soft à 6 et un hard à 15 est plus utile qu'un hard à 5 qui déclenche tout le temps.

Certains jobs sont « travail rapide plus longue attente ». Attendre une API externe, un upload de fichier, ou un fournisseur de paiement peut suspendre la progression sans que le job soit cassé. Gérez cela en donnant à chaque étape sa propre limite, pour voir où le temps est consommé.

Une façon simple de régler les timeouts

Utilisez ceci comme point de départ, puis ajustez selon les données réelles :

  • Soft timeout : 1,5× à 2× votre run normal le plus lent
  • Hard timeout : 3× à 5× votre run normal le plus lent
  • Timeouts par étape : définissez‑les pour chaque appel externe ou attente, en fonction du comportement normal du service

Quand un timeout déclenche, décidez du comportement à l'avance. Options simples : marquer comme bloqué et alerter quelqu'un, relancer si c'est sûr, ou arrêter et exiger une revue.

Raisons courantes pour lesquelles les jobs se bloquent (sans jargon code)

Hérité d'un build Replit
Nous stabilisons les apps générées par IA depuis Cursor, v0, Bolt et Replit.

La plupart des jobs bloqués ne sont pas mystérieux. Ils attendent généralement quelque chose, sont bloqués par quelque chose, ou répètent la même étape sans progresser.

Quatre causes reviennent souvent :

  • Le worker s'arrête en plein milieu. La machine qui exécute le job peut planter, redémarrer, manquer de mémoire, ou perdre le réseau. Le job a déjà démarré, donc il paraît « en cours », mais personne ne fait le travail.
  • Il attend un autre service qui ne répond jamais. Fournisseurs d'e‑mail, passerelles de paiement, API d'IA, stockage de fichiers, systèmes partenaires. Si le service se fige (pas une erreur claire), votre job peut rester là indéfiniment sans limite.
  • Quelque chose le bloque dans la base de données. Un job peut tenter de mettre à jour un enregistrement pendant qu'un autre processus détient un verrou. De l'extérieur, il paraît inactif. Dedans, c'est un embouteillage.
  • Le job boucle ou refait le même travail. Un petit bug peut provoquer des retries sans fin, du traitement en double, ou une boucle qui n'atteint jamais « done ». Techniquement il tourne, mais il n'avance pas.

Une vérification rapide : s'est‑il arrêté de progresser, ou s'est‑il complètement arrêté ? Si un job est marqué running mais que "rows processed" n'a pas changé depuis 20 minutes, vous regardez une attente, un blocage, ou une boucle.

Alertes qui aident à agir

Une alerte n'est utile que si elle dit à une vraie personne quoi faire ensuite. Si elle indique juste « worker error » à 2 h du matin, les gens la désactiveront et vous perdrez l'intérêt de la surveillance.

Commencez par un canal que vous regardez déjà, comme l'e‑mail ou le chat d'équipe. Ajoutez l'escalade plus tard une fois que vous faites confiance aux alertes.

Alertez seulement sur des états sur lesquels quelqu'un peut agir : un job est bloqué (pas de heartbeat pendant X minutes), un job a échoué plusieurs fois de suite, ou la file s'accumule (par exemple, le job le plus ancien a plus de 15 minutes). Évitez les alertes "FYI" comme « job started » sauf si vous déboguez.

Chaque alerte devrait contenir assez de contexte pour décider rapidement :

  • Nom du job et fonctionnalité concernée
  • Utilisateur ou compte affecté (si applicable)
  • Heure de début et dernier heartbeat
  • Dernière étape connue (par exemple : "Generating PDF")
  • Propriétaire et première action

Rendez la première action explicite et ennuyeuse. Exemple : « Propriétaire : Support. Première action : relancer une fois. Si ça échoue encore, escalader en Engineering avec cet ID de job. »

Étapes à suivre : rendre les jobs diagnostiquables en une journée

Triez une tâche bloquée aujourd'hui
Partagez l'exécution qui échoue et nous identifions où la progression s'arrête et pourquoi.

Vous pouvez rendre la détection des jobs bloqués opérationnelle en une journée si vous restez simple : définissez ce qu'est la santé, puis mesurez‑la.

Commencez par lister la poignée de jobs en arrière‑plan qui feraient du tort s'ils s'arrêtaient silencieusement (synchronisation de facturation, rapports nocturnes, envois d'e‑mails, imports de fichiers). Pour chacun, définissez ce que signifie « terminé » en termes simples : une ligne sauvegardée, un rapport livré, un lot d'e‑mails complété, un fichier marqué traité.

Ensuite, ajoutez un heartbeat. C'est juste un horodatage que votre job met à jour pendant son exécution. Mettez‑le à jour au démarrage, ponctuellement pendant la progression, et une fois à la fin. Maintenant « ça ne fonctionne pas » devient « le dernier heartbeat date de 23 minutes pendant l'étape 3. »

Puis définissez une règle de timeout par job. Basez‑la sur des heartbeats manquants pour les travaux longs ou sur un temps d'exécution maximum pour les courts. Choisissez quelque chose de réaliste basé sur le comportement normal, pas l'optimiste.

Enfin, donnez‑vous un seul endroit à consulter. Quatre états suffisent :

  • Running (heartbeat récent)
  • Done (marqueur de fin enregistré)
  • Failed (erreur enregistrée)
  • Stuck (timeout déclenché)

Prouvez que ça marche

Testez en forçant une panne volontairement : arrêtez le worker en plein job ou simulez un crash. Confirmez deux choses : le job apparaît comme bloqué, et l'alerte inclut quel job c'est, quand il a démarré, et le dernier heartbeat.

Une fois en place, vous n'êtes plus dans la conjecture. Vous observez.

Erreurs courantes et pièges à éviter

L'objectif est simple : quand quelque chose cesse de bouger, vous le savez vite et vous savez quoi faire ensuite. Les équipes ratent souvent cet objectif parce que les signaux restent « verts » jusqu'à ce qu'un client se plaigne.

Un piège courant est de traiter un seul signal « started » comme un heartbeat. Si votre worker ne rapporte qu'au début, un gel en milieu de job peut paraître sain pendant des heures.

Les timeouts se retournent aussi contre vous quand ils sont fixés au doigt mouillé. S'ils sont trop serrés pour les runs lents normaux (rapports de fin de mois, gros imports, pics de trafic), vous alerterez pour du travail qui aurait fini correctement. Les gens apprendront à ignorer les alertes, et alors tout est vain.

Les retries sont une autre source silencieuse de dégâts. Si un job peut s'exécuter deux fois et provoquer une double facturation, un e‑mail en double, ou un double remboursement, le retry automatique transforme une erreur en cauchemar pour le support.

Les alertes sont difficiles à traiter quand elles manquent d'éléments de base : quel client est affecté, quelle étape a été atteinte, qui en est le propriétaire, et si quelqu'un l'a déjà pris en charge.

Un contrôle de réalité utile : si une alerte réveille quelqu'un, il doit pouvoir répondre « qu'est‑ce qui a cassé, qui est affecté, et quelle est la prochaine action sûre » en moins de deux minutes. Si ce n'est pas le cas, l'alerte n'est pas efficace.

Liste de contrôle rapide avant déploiement de la surveillance

Avant de déployer, visez un seul résultat : quand quelqu'un dit « ça ne fonctionne pas », vous pouvez répondre ce qui s'est arrêté, quand, et quoi faire ensuite.

  • Pour tout job marqué « running », pouvez‑vous voir rapidement quand il a last check‑in ?
  • Avez‑vous une règle simple pour « stuck », écrite en une seule phrase (par exemple : « pas de check‑in pendant 10 minutes signifie bloqué »)?
  • Lorsqu'une alerte se déclenche, indique‑t‑elle quel job, quel client/espace de travail, quand il a progressé pour la dernière fois, et la dernière étape complétée ?
  • Si vous relancez, êtes‑vous protégé contre les doublons (double facturation, envoi d'e‑mails en double, création de deux rapports) ?
  • En cas d'urgence, quelqu'un peut‑il mettre en pause ou relancer le job sans toucher au code, et est‑il clair qui peut le faire ?

Un test pratique : demandez à un collègue non technique de lire une alerte et d'expliquer ce qu'il ferait ensuite. S'il ne peut pas, l'alerte n'est pas prête.

Scénario exemple : le rapport manquant qui était en fait bloqué

Expédiez en toute confiance
Préparez le déploiement et le nettoyage pour que votre système de tâches se comporte bien en trafic réel.

Un fondateur clique sur « Generate report » pour un client, ferme l'onglet et attend. Dix minutes plus tard, rien n'apparaît ni par e‑mail ni dans l'app. Le message au support est bref : « Ça ne fonctionne pas. »

Avec la détection en place, le tableau donne une histoire plus claire :

  • Job ID #18422 démarré à 10:03
  • Étape courante : "Export to PDF"
  • Dernier heartbeat : il y a 18 minutes
  • Statut : Stuck (heartbeat attendu toutes les 60 secondes)

Une alerte utile arrive au bon endroit et dit l'essentiel :

  • Le job de rapport est bloqué sur « Export to PDF »
  • Dernière progression : 12 430 lignes traitées
  • Compte affecté : Acme Co
  • Action sûre : relancer depuis l'étape d'export (pas de double facturation, pas d'e‑mails en double)

La personne en on‑call a alors un chemin clair. D'abord, elle redémarre le job en sécurité, en utilisant un retry qui réutilise le même enregistrement de sortie au lieu d'en créer un second. Le client reçoit son rapport.

Ensuite, on corrige la cause. Dans ce cas, c'est souvent soit un appel dans l'étape d'export qui ne renvoie jamais, soit un verrou en base qui fige la requête jusqu'à ce que le worker abandonne.

La prochaine fois, c'est plus calme car le job est découpé en étapes plus claires, et chaque étape a son propre timeout.

Prochaines étapes : rendez vos jobs fiables et faciles à supporter

Commencez petit. Choisissez le job en arrière‑plan qui cause le plus de douleur (rapports manquants, factures échouées, e‑mails retardés). Ajoutez des heartbeats et une règle de timeout simple à ce job en premier. Vous apprendrez plus avec un job bien instrumenté qu'avec une surveillance légère partout.

Écrivez ce que « sain » signifie en clair pour que n'importe qui puisse le juger d'un coup d'œil. Exemple : « Ce job doit mettre à jour son heartbeat au moins une fois par minute et se terminer en 8 minutes. S'il dépasse, il doit alerter. » Cette phrase devient votre définition partagée de la normale.

Si votre codebase a commencé comme un prototype généré par IA, supposez qu'il y a des cas limites cachés même si tout semble fonctionner la plupart du temps. Les pannes apparaissent souvent comme des jobs bloqués parce qu'un worker attend indéfiniment, échoue silencieusement, ou relance d'une manière qui rend les données incohérentes.

Si vous gérez une app générée par IA qui se fige en arrière‑plan et que vous voulez une voie rapide et pratique vers la production, FixMyMess (fixmymess.ai) se concentre sur le diagnostic et la réparation de problèmes comme les heartbeats manquants, les retries dangereux, et la logique des workers cassée pour rendre vos jobs observables et supportables.

Une fois le minimum stabilisé, vos évolutions habituelles sont : retries plus sûrs (exécutables deux fois sans effet néfaste), une page de statut simple pour la santé des jobs, et des vérifications de déploiement qui détectent les problèmes de configuration avant la mise en production.

Questions Fréquentes

What exactly is a background job?

Un job en arrière-plan est un travail que votre app exécute après qu'un utilisateur ait cliqué quelque chose, sans le laisser sur un écran de chargement. Exemples courants : génération de rapports, import CSV, export PDF et envoi d'e-mails.

Why does “it’s not running” feel so hard to debug?

Parce que trois situations différentes peuvent apparaître identiques depuis l'extérieur : le job est lent, il a échoué, ou il est bloqué. Sans signaux comme des mises à jour de progression ou des horodatages, on ne peut pas savoir lequel c'est.

How can I tell if a job is slow rather than stuck?

« Lent » veut dire que le job avance toujours, juste plus lentement que prévu. Vous verrez des preuves comme des horodatages qui s'actualisent, des compteurs qui augmentent, ou de nouvelles lignes de log/mises à jour de progression.

What’s the difference between a failed job and a stuck job?

Un job échoué s'est arrêté et ne se terminera pas tout seul. Il se termine par une erreur ou rencontre un problème bloquant ; la seule façon d'achever le travail est de corriger la cause puis de relancer en toute sécurité.

What is a heartbeat and why do I need it?

Un heartbeat est une petite mise à jour « preuve de vie » que le job écrit pendant son exécution, comme un horodatage ou un compteur d'éléments traités. Si les heartbeats cessent de s'actualiser, vous avez un signal clair que le job ne progresse plus.

What’s the simplest way to add heartbeats without overengineering?

Suivez un seul enregistrement par exécution de job, par exemple last_heartbeat_at, current_step et un nombre de progression basique. Mettez-le à jour uniquement après l'achèvement d'une vraie unité de travail afin qu'il reflète un vrai progrès, pas une boucle qui tourne.

How do I choose timeouts that won’t spam me with false alerts?

Commencez par un soft timeout pour signaler « inhabituellement lent », puis un hard timeout pour déclarer « bloqué ». Par défaut pratique : mettez le soft autour de 1,5–2× votre run normal le plus lent, et le hard autour de 3–5×.

What are the most common real reasons jobs get stuck?

Causes fréquentes : le worker plante en cours d'exécution, un service tiers ne répond pas, un verrou en base de données bloque les mises à jour, ou un bug boucle et répète la même étape. Les heartbeats plus un champ « dernière étape » indiquent généralement laquelle de ces catégories c'est.

What should a good stuck-job alert include?

Incluez le nom du job, l'utilisateur/le compte affecté, l'heure de début, le dernier heartbeat, la dernière étape connue, et la première action sûre à entreprendre (relancer une fois, mettre en pause, ou escalader). Si l'alerte n'indique pas quoi faire ensuite, elle sera ignorée.

What’s a one-day plan to make stuck jobs diagnosable?

Choisissez le job le plus problématique et définissez en termes clairs ce que signifie « terminé ». Ajoutez un heartbeat, fixez une règle de timeout, et montrez quatre états : Running, Done, Failed, Stuck — ainsi tout le monde voit rapidement ce qui se passe.