Quartz.NET vs Hangfire : le bon scheduler pour les apps .NET
Quartz.NET et Hangfire résolvent des problèmes qui se recoupent mais diffèrent dans le traitement en arrière-plan .NET. Voici le vrai compromis, et une troisième option pour la part qui consiste juste à « exécuter ceci selon un planning ».
Chaque équipe .NET qui exécute du travail planifié ou en arrière-plan se pose tôt ou tard la même question : Quartz.NET ou Hangfire ? La réponse honnête est qu’ils se recoupent moins que ne le suggèrent les articles comparatifs — ils ont été conçus pour des tâches légèrement différentes, et un mauvais choix se traduit surtout par de la friction plus tard, pas par une réécriture.
Quartz.NET : un scheduler, avant tout
Quartz.NET est un portage de la bibliothèque Java Quartz — un moteur de
planification. Construit autour de ITrigger et IJob, d’expressions cron,
de calendriers (ignorer les jours fériés, fenêtres heures de bureau
uniquement) et d’un support de cluster pour faire tourner le même scheduler
sur plusieurs nœuds sans déclenchement double. Il ne fournit pas de file de
jobs, de tableau de bord, ni de modèle pour « mettre en file depuis une
requête web et traiter plus tard » — ce n’est pas son rôle. Vous définissez
jobs et triggers en code ou en config, et Quartz les déclenche.
Si votre problème est vraiment « une planification précise, sensible au calendrier, en cluster, pour du travail in-process », Quartz.NET est conçu exactement pour ça, d’une façon que rien d’autre dans l’écosystème .NET n’égale tout à fait.
Hangfire : du traitement en arrière-plan avec persistance
Hangfire part d’un angle différent : le traitement fiable de jobs en
arrière-plan. BackgroundJob.Enqueue(() => SendEmail(id)) depuis une action
de contrôleur, relancé automatiquement en cas d’échec, visible dans un tableau
de bord, persisté dans SQL Server ou Redis pour que les jobs survivent à un
redémarrage de l’app. Il supporte aussi les jobs récurrents
(RecurringJob.AddOrUpdate), c’est là que le recoupement avec Quartz
commence — mais le design centré sur le stockage et le tableau de bord est le
vrai facteur de différenciation, pas la syntaxe de planification.
Si votre problème est « du travail en arrière-plan déclenché par des événements applicatifs, avec relances et visibilité », Hangfire est le choix le plus direct — la persistance et le tableau de bord sont intégrés.
Là où ils se recoupent vraiment
Le recoupement est étroit : les jobs récurrents, pilotés par planning, sans
déclencheur entrant — un rapport nocturne, une tâche de nettoyage, un email
de synthèse. Quartz.NET peut le faire avec un CronTrigger. Hangfire peut le
faire avec RecurringJob.AddOrUpdate. Les deux fonctionnent. Aucun n’est un
mauvais choix. Le facteur décisif est généralement celui que votre app a déjà
câblé pour ses autres types de jobs — ajouter une seconde bibliothèque de
planification juste pour les jobs récurrents en vaut rarement la peine.
L’option qu’aucun article comparatif ne mentionne
Les deux bibliothèques tournent à l’intérieur de votre processus applicatif, ce qui signifie que le CPU, la mémoire et les connexions base de données d’un job récurrent proviennent du même pool qui sert les requêtes. Un job de rapport qui verrouille des lignes pendant 90 secondes tourne dans le même processus — et souvent contre la même base de données — censé répondre aux requêtes HTTP en même temps.
Pour le sous-ensemble de jobs purement pilotés par planning, qui n’ont pas besoin des calendriers en cluster de Quartz ni du modèle file/continuation de Hangfire, vous pouvez vous passer des deux et externaliser entièrement le déclencheur : exposer un endpoint HTTP, et faire en sorte que quelque chose hors de votre processus l’appelle selon le planning, avec son propre réessai/backoff et journal d’exécution. C’est toute l’idée derrière SteadyCron — voir le détail complet dans SteadyCron vs Hangfire pour savoir où ce compromis se situe vraiment, y compris pour les jobs que vous voulez continuer à laisser à Quartz.NET ou Hangfire.
Faire son choix
- Quartz.NET si vous avez besoin d’une planification sensible au calendrier ou en cluster pour des jobs in-process, et que vous n’avez pas besoin de file de jobs.
- Hangfire si vous avez besoin d’une file de jobs avec persistance et tableau de bord, et que les jobs récurrents sont une fonctionnalité secondaire que vous utiliserez en plus.
- Aucun des deux, pour le sous-ensemble purement planifié, si le job n’a pas besoin de tourner dans votre app du tout — sortir le déclencheur élimine complètement la bibliothèque de planification et son stockage de l’équation.