Choisissez un périmètre assez petit pour être vérifié
Une migration progressive peut réduire la portée de chaque mise en production, mais elle n’est pas sans risque. Commencez par un flux délimité dont les entrées, les sorties et les responsables sont bien compris. Cartographiez le modèle de données existant, les effets externes et les dépendances de reporting avant de basculer du trafic.
Relevez comme référence le taux d’erreurs, la latence des réponses, l’âge de la file d’attente et les résultats métier, comme les commandes finalisées. Dirigez un ensemble contrôlé de requêtes vers la nouvelle implémentation et conservez un chemin de retour clair. Évitez de migrer en même temps le stockage, le framework, les paiements et l’interface, sauf si les dépendances l’imposent.
Gardez l’écriture critique transactionnelle
Validez les permissions et les données saisies, puis enregistrez la transition d’état minimale valide dans une transaction de base de données. Utilisez des contraintes d’unicité pour les invariants, par exemple une seule référence externe par commande. Les verrous de ligne ou les mises à jour conditionnelles peuvent protéger les transitions concurrentes lorsqu’ils sont bien utilisés.
Un verrou Redis peut coordonner le travail, mais un bail expiré, un plantage ou une clé mal délimitée peuvent laisser des exécutions se chevaucher. Il ne remplace pas les contraintes de la base de données. Documentez quel système est responsable de chaque invariant et testez-le avec des requêtes simultanées.
Ne déclenchez un job qu’une fois les données validées
Un worker peut s’exécuter avant que la transaction qui l’a créé ne soit validée. Laravel permet de déclencher un job après la validation, pour qu’il ne lise pas des enregistrements non validés ou annulés. Dans une application Laravel 12, un schéma de base ressemble à ceci :
DB::transaction(function () use ($validated) {
$order = Order::create($validated);
ProcessOrder::dispatch($order->id)->afterCommit();
});
Cet exemple est volontairement incomplet : l’autorisation, la gestion des requêtes en double et la validation métier viennent s’y ajouter. Le déclenchement après validation n’élimine pas non plus la fenêtre de panne entre la validation en base et la remise à une file d’attente externe. Pour les flux qui exigent une livraison durable, envisagez un outbox transactionnel et un publieur qui réessaie.
Concevez les jobs pour une exécution « au moins une fois »
Partez du principe qu’un job peut s’exécuter plusieurs fois. Enregistrez une clé d’idempotence, suivez les opérations terminées et utilisez le mécanisme d’idempotence du fournisseur externe lorsqu’il existe. Ne marquez pas un job comme terminé avant que l’effet externe n’ait réussi. Rapprochez les résultats incertains au lieu de répéter aveuglément un débit ou une expédition.
- Définissez les délais d’expiration, les limites de tentatives et les temporisations selon l’opération.
- Gardez le délai d’expiration du worker inférieur à l’intervalle de nouvelle tentative de la file, avec une marge pour l’arrêt, afin de limiter les tentatives qui se chevauchent.
- Surveillez les jobs en échec et l’âge de la file ; une réponse HTTP 202 signifie « accepté », pas « terminé ».
- Redémarrez les workers de longue durée lors des mises en production pour qu’ils chargent le bon code.
Répétez les pannes et le retour arrière
Testez un webhook en double, le plantage d’un worker après un appel externe, un interblocage en base de données, une panne de la file d’attente et un déploiement raté. Vérifiez les enregistrements et les effets obtenus, pas seulement la réponse HTTP. Ajoutez un rapprochement pour le travail accepté mais jamais terminé.
Utilisez des changements de schéma rétrocompatibles tant que les deux applications sont actives. Définissez les conditions de retour arrière avant la mise en production et vérifiez que l’ancienne application sait lire les données écrites par la nouvelle. Gardez une source de vérité unique pour chaque enregistrement tant que la synchronisation n’est pas conçue explicitement.
Questions fréquentes
Quand un traitement doit-il rester synchrone ?
Lorsque l’appelant a besoin d’un résultat immédiat et définitif, et que le traitement est assez court pour respecter le temps de réponse prévu. Les files d’attente sont utiles pour le travail différable, mais elles apportent leurs propres responsabilités de livraison, de visibilité et de reprise.
Le déclenchement après validation garantit-il que le job arrive dans la file ?
Non. Il empêche de déclencher un job avant la validation de sa transaction, mais une panne peut encore survenir entre la validation et la remise à une file externe. Si vous avez besoin d’une livraison durable, évaluez un outbox transactionnel avec un publieur qui réessaie et un rapprochement.
Comment éviter que les nouvelles tentatives créent des paiements ou des commandes en double ?
Utilisez des clés d’idempotence persistantes, des contraintes en base de données et le mécanisme d’idempotence du fournisseur externe lorsqu’il existe. Suivez les résultats et rapprochez les réponses incertaines. Un verrou de courte durée ne couvre pas à lui seul tous les plantages ni toutes les fenêtres de nouvelle tentative.
Qu’est-ce qui facilite le retour arrière d’une migration progressive ?
Déplacer un flux délimité, conserver un chemin clair vers l’implémentation précédente et utiliser des changements de schéma rétrocompatibles. Vérifiez que l’ancienne application sait lire les enregistrements créés par la nouvelle. Définissez avant la mise en production les déclencheurs de retour arrière, fondés sur les erreurs et les résultats métier.
Sources et lectures complémentaires
- Laravel 12 : files d’attente, déclenchement après validation et délais
- Laravel 12 : transactions de base de données
Pour aller plus loin
Comparez les stratégies de rendu ou parlons d’une migration vers Laravel.

Leave a Reply