1. Accueil
  2. Notes techniques
  3. Concevoir une retry queue persistée

Concevoir une retry queue persistée

Livraison garantie d'événements sans broker : PostgreSQL, backoff exponentiel, reprise après redémarrage.

Fiable2 min de lecture
En 10 secondes

Quand un destinataire d'événement est indisponible, deux échecs guettent : perdre le message en silence, ou le marteler sans répit. Le pattern : persister chaque livraison en attente dans PostgreSQL avec l'échéance de son prochain essai, retenter en backoff exponentiel, et reprendre la file telle quelle après un redémarrage. Implémenté dans le Hub.

Le problème

Un service central reçoit des événements et doit les livrer : notifications, webhooks sortants. Les destinataires tombent, redémarrent, dépassent les délais. Deux échecs classiques :

  • La perte silencieuse. L’envoi échoue, on loggue, on passe. Le message n’existe plus, et personne ne s’en aperçoit avant que ça compte.
  • Le retry en mémoire. Mieux, jusqu’au premier redéploiement, où la file disparaît avec le processus.

Le pattern

Traiter la livraison comme un état persisté :

  • Chaque livraison est une ligne dans PostgreSQL : événement, destination, nombre d’essais, échéance du prochain essai, statut.
  • Backoff exponentiel. Chaque échec repousse l’échéance suivante de plus en plus loin. On laisse au destinataire le temps de se remettre au lieu de le marteler.
  • Un worker réclame ce qui est dû, c’est-à-dire les livraisons dont l’échéance est passée, de façon transactionnelle : l’état ne ment jamais.
  • Reprise gratuite. Après un crash ou un déploiement, la file est toujours là. Le worker reprend exactement où l’état l’indique. Combiné au graceful shutdown, un redéploiement ne coupe rien à mi-chemin.
  • Borne et visibilité. Au-delà d’un nombre d’essais, la livraison passe en échec définitif : visible, requêtable en SQL, jamais évaporée.

Pourquoi pas un broker ?

RabbitMQ ou un équivalent fournit tout ça nativement, au prix d’une pièce stateful critique supplémentaire à exploiter, sauvegarder et superviser. Sur une plateforme mono-nœud dont la base est déjà sauvegardée et connue, le compromis penche pour PostgreSQL : les garanties viennent des transactions, et l’outillage de diagnostic est du SQL. Le jour où le débit l’exige, l’interface de publication permet de changer d’implémentation sans toucher au reste.

Les leçons

  • L’idempotence est la moitié du pattern. Un retry peut livrer deux fois, le destinataire doit pouvoir l’encaisser.
  • Le backoff protège les deux bouts. Le destinataire respire, et l’émetteur ne brûle pas ses ressources sur un service injoignable.
  • Un échec définitif doit se voir. Une file qui avale les erreurs sans bruit reproduit le problème initial, avec une étape de plus.

← Toutes les notes