Développement web

Migration Symfony : monter de version sans casser le run

Jérémy Chomel Dawap
  • Publié le : 16 juillet 2026
  • Temps de lecture : 14 minutes
  1. Pour qui une migration Symfony est d’abord un risque de run
  2. Choisir la version cible et la trajectoire de migration
  3. Inventorier dépendances, bundles et intégrations avant de modifier Composer
  4. Supprimer les dépréciations et construire une baseline de tests
  5. Migrer par étapes sans mélanger refonte métier et montée de framework
  6. Protéger données, sessions, cache, messages et tâches planifiées
  7. Déployer progressivement avec critères de rollback
  8. La matrice go, réserve ou no-go d’une migration Symfony
  9. Erreurs fréquentes qui transforment un upgrade en refonte cachée
  10. Plan d’action 30, 60 et 90 jours
  11. Pour aller plus loin
  12. Sources officielles
  13. Conclusion : rendre la migration réversible avant de la rendre rapide
Jérémy Chomel

Une migration Symfony n’est pas un simple changement de contrainte Composer. Le vrai enjeu est de réduire le risque de rupture sur le framework, PHP, les dépendances, la configuration, les données, les workers, les sessions, le cache, les tâches planifiées et les contrats avec les systèmes tiers.

La version cible n’est sûre que lorsque ces composants ont été traités comme un seul système. Un signal faible apparaît quand le code compile mais que personne ne sait expliquer le devenir des messages en attente, des webhooks, des crons ou des sessions pendant un déploiement mixte.

La page migration d’application legacy Symfony reste la page propriétaire pour cadrer une trajectoire, un audit de compatibilité et un plan de bascule. Le présent guide donne la méthode de montée de version sans promettre une absence universelle d’interruption.

Vous allez comprendre comment stabiliser la version source, rendre les dépréciations visibles, traiter les dépendances incompatibles, migrer par étapes et définir le rollback avant le go-live. Contrairement à ce que suggère une application qui démarre, une migration rapide mais irréversible reste un risque de run, pas un succès technique.

Pour qui une migration Symfony est d’abord un risque de run

La migration concerne le responsable applicatif qui répond de la continuité du service, le tech lead qui maîtrise la compatibilité, les métiers qui valident les parcours critiques et l’équipe de run qui surveille puis reprend les incidents. Aucun de ces rôles ne peut valider seul l’ensemble du risque.

Le chantier devient particulièrement sensible lorsque l’application gère des commandes, dossiers clients, factures, documents, droits, traitements différés ou échanges avec un ERP et un CRM. Le risque ne vient alors pas seulement d’une erreur HTTP. Il vient d’un message rejoué, d’une session invalide, d’une migration de données incompatible ou d’un webhook traité deux fois pendant la bascule.

Une petite application interne peut parfois accepter une coupure planifiée. Une application critique peut exiger un déploiement progressif et une compatibilité temporaire entre deux versions. La méthode doit partir de la criticité et des fenêtres acceptables, pas d’une recette de migration générique.

Le sponsor doit aussi décider ce que la migration n’est pas. Si le chantier ajoute de nouveaux parcours, remplace le modèle métier et change l’interface, il devient une refonte. Mélanger ces objectifs rend les anomalies plus difficiles à attribuer et le rollback beaucoup moins crédible.

Choisir la version cible et la trajectoire de migration

La page officielle Symfony releases doit être contrôlée le jour de l’intégration puis avant la décision, car les branches maintenues et leurs calendriers évoluent. Le bon choix dépend de la version source, de PHP, des dépendances et de l’horizon de maintenance recherché.

Évitez de choisir la cible uniquement parce qu’elle est la plus récente. Une version intermédiaire peut être nécessaire pour rendre les dépréciations visibles, mettre à jour des bundles et réduire la taille du saut. À l’inverse, multiplier les étapes sans raison augmente le nombre de bascules. La trajectoire doit être justifiée composant par composant.

Le guide officiel Upgrading a major version recommande notamment de supprimer les dépréciations, de mettre à jour les dépendances et de lire les documents de rupture de compatibilité. Le guide Upgrading a patch version rappelle qu’une mise à jour de patch suit un cadre différent. Il ne faut pas traiter une montée majeure comme un simple patch.

Écrivez une trajectoire qui indique : version source stabilisée, versions intermédiaires éventuelles, cible, version PHP, dépendances bloquantes, étapes de recette, déploiements et points de retour. Chaque étape doit avoir une preuve attendue et une décision possible.

Un chemin raisonnable peut ressembler à ceci : assainir l’existant, atteindre la dernière mineure compatible de la branche source, retirer les dépréciations, mettre à jour les dépendances, franchir une majeure, stabiliser, puis recommencer si la cible est plus loin. Ce chemin reste un exemple de méthode, pas une commande universelle.

Un second signal faible est une dépendance déclarée « probablement compatible » sans test sur la version cible. Avant que le blocage ne se voie en recette, l’absence de propriétaire, de preuve et de solution de repli indique déjà que la trajectoire n’est pas maîtrisée.

Inventorier dépendances, bundles et intégrations avant de modifier Composer

L’inventaire commence avant le premier composer update. Il doit couvrir :

  • versions de PHP, Symfony et Composer ;
  • composants Symfony directement requis ;
  • bundles et bibliothèques avec leurs contraintes ;
  • recettes Flex, configuration et variables d’environnement ;
  • contrôleurs, événements, sérialisation, formulaires et sécurité ;
  • Doctrine, extensions, migrations et volumes de données ;
  • Messenger, workers, files, crons et commandes planifiées ;
  • sessions, cache, fichiers et stockage objet ;
  • clients API, webhooks, emails et contrats tiers ;
  • tests unitaires, intégration, fonctionnels et parcours critiques ;
  • métriques, logs, traces, alertes et runbooks.

Quelques commandes peuvent aider à construire l’état des lieux. Elles doivent être exécutées sur une branche dédiée et relues selon la version du projet :

php bin/console about
composer show 'symfony/*'
composer outdated 'symfony/*'
composer why-not symfony/framework-bundle 'VERSION_CIBLE'
composer validate --strict

VERSION_CIBLE est volontairement un placeholder. Elle doit être remplacée par une contrainte vérifiée dans le projet. La sortie de why-not identifie les contraintes qui empêchent l’installation ; elle ne décide pas si une dépendance doit être mise à jour, remplacée ou retirée.

La dépendance la plus risquée n’est pas forcément Symfony. Un bundle abandonné, une bibliothèque de génération de documents, une extension Doctrine ou un SDK tiers peut imposer davantage de travail. Pour chaque composant, relevez l’usage réel, la version source, la cible compatible, la preuve et la décision.

Inspectez également les recettes et les fichiers de configuration. Une mise à jour de package peut proposer une nouvelle recette sans que son application automatique soit souhaitable. Comparez les changements, documentez les écarts locaux et ne remplacez pas une configuration métier par défaut sans revue.

Supprimer les dépréciations et construire une baseline de tests

Les dépréciations sont un programme de travail, pas un bruit de log. Elles signalent ce qui fonctionnera différemment ou disparaîtra lors de la montée majeure. Elles doivent être visibles dans les environnements de développement et de test, puis suivies jusqu’à un niveau accepté explicitement.

Commencez par séparer les dépréciations du code applicatif de celles des dépendances. Les premières peuvent être corrigées directement. Les secondes demandent une mise à jour, un remplacement, une contribution ou une décision de risque. Masquer toutes les dépréciations pour obtenir une CI verte reporte l’information au pire moment.

La baseline de tests doit précéder la migration. Elle fixe le comportement de la version source : parcours critiques, règles métier, droits, sérialisation, commandes, messages, intégrations et performances utiles. Un test écrit après la rupture peut involontairement valider le nouveau comportement au lieu de protéger l’ancien.

La couverture ne se résume pas à un pourcentage. Listez les décisions que le système doit préserver : un statut ne peut pas régresser, un rôle ne peut pas exporter hors périmètre, une facture ne peut pas être créée deux fois, un message en erreur doit rester reprenable et un webhook doit être dédupliqué.

Utilisez ensuite la CI pour suivre les dépréciations et les écarts. Le composant Symfony PHPUnit Bridge peut aider à rendre leur budget explicite selon la configuration du projet. Toute option copiée d’un exemple doit être vérifiée avec la version réellement installée.

Migrer par étapes sans mélanger refonte métier et montée de framework

Une migration progressive réduit le nombre de variables modifiées à chaque étape. Mettez d’abord à niveau le code et les dépendances tout en conservant le comportement fonctionnel. Les refontes d’interface, changements de workflow et nouvelles règles métier viennent dans des lots séparés.

Cette discipline facilite le diagnostic. Si une sérialisation change après la montée de composant, l’équipe sait où chercher. Si le même lot modifie aussi l’objet métier, le contrôleur et l’interface, la cause devient ambiguë et le retour arrière peut supprimer une évolution attendue.

Les changements doivent rester petits et testables : correction de dépréciations, remplacement d’une API framework, mise à jour d’un bundle, adaptation d’une recette, montée de version, puis stabilisation. Chaque commit doit expliquer la compatibilité visée et la preuve exécutée.

Ne remplacez pas automatiquement une dépendance abandonnée par une nouvelle abstraction globale. Commencez par isoler son usage derrière une interface locale, écrire des tests de comportement, puis changez l’implémentation. Cette approche borne le risque et rend une sortie possible si la nouvelle bibliothèque ne convient pas.

Le même principe s’applique aux contrôleurs, événements et sécurité. La migration peut exiger une nouvelle API, mais elle n’impose pas de redessiner tout le domaine. Protégez les règles métier de la variabilité du framework.

Protéger données, sessions, cache, messages et tâches planifiées

Les données imposent souvent les contraintes les plus fortes. Une migration additive — ajouter une colonne nullable, écrire les deux formats temporairement, remplir les données puis rendre la nouvelle structure obligatoire — permet parfois une coexistence. Elle n’est pas toujours possible. Toute irréversibilité doit être écrite avant la bascule.

Une migration Doctrine techniquement réversible ne garantit pas un rollback métier. Si la nouvelle version transforme une donnée ou déclenche des effets externes, revenir au schéma précédent peut perdre de l’information. Le plan doit distinguer rollback du code, rollback du schéma et stratégie de correction des données.

Les sessions doivent rester lisibles pendant un déploiement mixte ou être invalidées de façon assumée. Vérifiez le format, le stockage, les cookies et les changements de sécurité. Un utilisateur déconnecté peut être acceptable ; une action interrompue sans explication peut ne pas l’être.

Le cache peut contenir des objets sérialisés, routes, templates ou résultats dépendants de la version. La stratégie de purge doit éviter qu’un ancien worker lise un format produit par la nouvelle version, ou inversement. Une purge totale peut aussi créer un pic de charge : elle doit être testée.

Messenger demande une attention particulière. Des messages produits avant la bascule peuvent être consommés après. Vérifiez les classes, enveloppes, stamps, sérialiseurs, retries, transports et dead-letter queues. Une modification de message doit prévoir une compatibilité, une migration de file ou une vidange contrôlée.

Les crons et commandes planifiées doivent être inventoriés avec leurs verrous. Pendant la bascule, deux versions peuvent exécuter la même tâche. Il faut décider laquelle est active, comment éviter le doublon et comment reprendre une exécution interrompue.

Enfin, testez les clients API et webhooks. Les contrats tiers peuvent dépendre d’une sérialisation, d’un header, d’un timeout ou d’un comportement d’exception modifié par une bibliothèque. Le test doit couvrir le flux sortant, la réponse et la reprise, pas seulement l’instanciation du client.

Déployer progressivement avec critères de rollback

Un déploiement progressif ne protège que ce qui est mesuré. Avant la première requête, écrivez les seuils qui autorisent la poursuite ou déclenchent l’arrêt : erreurs HTTP, exceptions, latence, échecs métier, messages en attente, rejets d’intégration, saturation et capacité du support.

Comparez ces métriques à une baseline de la version source. Un taux d’erreur nul en recette n’a pas de sens s’il manque le volume et les cas réels. La comparaison doit utiliser une fenêtre suffisamment représentative et distinguer un incident ponctuel d’une dérive.

Selon l’architecture, le déploiement peut prendre la forme d’un canary, d’un blue-green ou d’une bascule par périmètre. Aucun modèle n’est universel. L’objectif est de limiter l’exposition, observer un trafic réel autorisé et conserver une décision de retour crédible.

Le rollback doit nommer un décideur et un opérateur. Il couvre le code, les données, les sessions, le cache, les messages, les crons et les effets externes. Pour chaque composant, écrivez ce qui revient automatiquement, ce qui doit être rapproché et ce qui est irréversible.

Un bon critère de rollback est observable et borné : nombre d’échecs métier sur un parcours critique, croissance du backlog Messenger, erreur d’authentification, divergence de données ou latence au-delà d’un seuil validé. « Si ça se passe mal » n’est pas un critère.

La matrice go, réserve ou no-go d’une migration Symfony

Contrôle Preuve attendue Go Réserve possible No-go
Version cible Releases officielles et compatibilité PHP Cible et horizon validés Étape intermédiaire planifiée Cible non compatible ou non justifiée
Dépendances Matrice complète et why-not relu Toutes décidées Remplacement borné après bascule Dépendance critique sans solution
Dépréciations Rapport CI attribué Budget accepté, code applicatif traité Dépendance tierce suivie et non bloquante Dépréciations masquées ou inconnues
Tests Baseline et parcours critiques verts Comportement protégé Cas secondaire planifié Parcours critique non testé
Données Migrations, volume et reprise testés Compatibilité ou rollback prouvé Correction manuelle bornée Transformation irréversible non assumée
Sessions et cache Déploiement mixte ou invalidation testée Comportement connu Déconnexion communiquée État incohérent possible
Messenger Messages anciens/nouveaux et files testés Compatibilité prouvée Vidange contrôlée Message perdu ou rejoué sans contrôle
Crons Inventaire, verrou et responsable Exécution unique Arrêt temporaire accepté Double traitement possible
API et webhooks Contrats, erreurs et replay testés Flux et reprise verts Partenaire surveillé Effet externe non rapprochable
Observabilité Baseline, alertes et runbook Seuils exploitables Surveillance renforcée bornée Incident invisible
Rollback Exercice et RACI Retour crédible Roll-forward documenté si irréversible Aucun chemin de sortie

Une réserve doit avoir une échéance et une condition de levée. Par exemple, une surveillance renforcée pendant une fenêtre bornée peut être acceptable si le rollback reste disponible. Une dépendance critique inconnue ou une migration irréversible non assumée appelle un no-go.

Erreurs fréquentes qui transforment un upgrade en refonte cachée

La première erreur est de profiter de la migration pour réécrire les règles métier. L’intention paraît efficace, mais elle mélange compatibilité et évolution fonctionnelle. La recette ne sait plus quel comportement protéger.

La deuxième erreur est de ne tester que les contrôleurs. Les workers, messages, crons, exports et webhooks vivent parfois plus longtemps qu’une requête. Ils traversent les versions et portent des effets métier que les tests HTTP ne voient pas.

La troisième erreur est de mettre à jour toutes les dépendances sans séquence. Un grand diff Composer peut résoudre les contraintes tout en changeant plusieurs comportements. Préférez des étapes attribuables et une stabilisation entre les majeures.

La quatrième erreur est de promettre « zéro interruption » sans architecture qui le permette. Une courte maintenance maîtrisée peut être moins risquée qu’une coexistence complexe. La décision doit refléter les contraintes réelles, pas un slogan.

Enfin, ne traitez pas le rollback comme un redéploiement. Les données, messages et appels externes peuvent avoir avancé. Si le retour au code précédent ne sait pas relire cet état, il faut une stratégie de compatibilité ou un roll-forward documenté.

Plan d’action 30, 60 et 90 jours

Jours 1 à 30 : rendre le risque visible

Stabilisez la source, contrôlez la cible officielle, inventoriez les composants et construisez la baseline. Rendez les dépréciations visibles. Cartographiez les parcours, messages, crons, données et intégrations. Identifiez les dépendances bloquantes et écrivez la première matrice de compatibilité.

À J+30, l’entreprise doit pouvoir décider une trajectoire, pas nécessairement avoir migré. Le livrable comprend les étapes, risques, preuves, responsables, budget et exclusions.

Jours 31 à 60 : réduire les incompatibilités

Traitez les dépréciations applicatives, isolez ou remplacez les dépendances bloquantes et renforcez les tests. Préparez les migrations de données compatibles, les formats de messages et les procédures de cache et sessions. Franchissez les étapes de version sur des environnements contrôlés.

À J+60, les principaux écarts doivent être attribués. Le runbook de bascule et de rollback existe déjà, même s’il doit encore être exercé.

Jours 61 à 90 : prouver la bascule

Exécutez la recette complète, la charge utile, les scénarios d’échec et un exercice de rollback. Déployez progressivement sur un périmètre autorisé, comparez les métriques à la baseline et rapprochez les effets métier. Corrigez les écarts avant d’élargir.

À J+90, la décision de généralisation repose sur des preuves. Si elles manquent, le calendrier doit s’adapter ; la cible technique ne justifie pas de prendre un risque métier non maîtrisé.

Par exemple, l’équipe peut poser comme hypothèse un seuil de rollback à 5 échecs métier sur 100 parcours critiques exécutés pendant le canary. Ce seuil n’est pas une norme Symfony : il doit être calibré avec la baseline, la criticité, le volume et la capacité réelle du support.

Le runbook attribue les entrées, sorties, dépendances et responsabilités de la bascule. Il précise la version de chaque worker, le format des messages, les verrous de cron et la personne qui décide si un état doit être repris, rapproché ou laissé en attente.

L’instrumentation relie monitoring, seuils, rollback et journalisation à un identifiant de corrélation. Le responsable du run doit pouvoir distinguer une erreur de framework, une divergence de données et un effet externe déjà exécuté avant d’autoriser un replay.

Pour aller plus loin

Le guide Refonte d’application métier sans casser l’exploitation approfondit les bascules progressives et la continuité de service. Le guide Priorités sécurité avant réécriture complète l’inventaire sur les droits, données, secrets et actions sensibles.

Pour replacer la migration dans la trajectoire produit globale, le hub développement d’application métier relie cadrage, refonte, intégration SI et exploitation.

Sources officielles

Conclusion : rendre la migration réversible avant de la rendre rapide

Une migration Symfony maîtrisée traite ensemble framework, dépendances, configuration, données, sessions, cache, messages, crons et intégrations. La réussite ne se mesure pas au seul démarrage de l’application cible, mais à la continuité des décisions métier et à la capacité du run à comprendre les écarts.

La bonne séquence consiste à stabiliser la source, supprimer les dépréciations, construire une baseline, migrer par étapes et prouver les critères de go et de rollback. Les changements métier restent séparés pour que chaque rupture soit attribuable.

Dawap peut vous accompagner pour auditer une application existante, choisir la cible et construire un plan de bascule vérifiable. Partez de la page migration d’application legacy Symfony : une migration responsable est d’abord une trajectoire exploitable et réversible ; la vitesse vient ensuite.

Jérémy Chomel

Vous avez un projet de
développement sur mesure ?

Nous concevons des applications métier, plateformes web et solutions e-commerce pensées pour durer : architecture API-first, automatisation des flux, performance et scalabilité au cœur du projet.

Besoin d’échanger sur votre projet ? Planifier un rendez-vous

Articles recommandés

Refonte d’application métier Développement web Refonte d’application métier sans casser l’exploitation Lire l'article
  • 3 janvier 2024
  • Lecture ~16 min

Refondre une application métier sans casser l’exploitation impose de traiter flux critiques, historiques, droits et retour arrière avant l’interface. Ce cadrage aide à décider quoi migrer, quoi différer et quels seuils mesurer pour sécuriser la bascule, limiter les écarts de données et éviter qu’un lift UI casse le run réel.

Refonte application métier et sécurité Développement web Refonte application métier : priorités sécurité à traiter Lire l'article
  • 15 juin 2026
  • Lecture ~11 min

Avant de réécrire une application métier, la sécurité doit sortir du flou: droits hérités, rôles trop larges, secrets, exports, données sensibles, journaux, dépendances et retour arrière. Ce guide aide à prioriser les risques non défendables, à décider quoi corriger tout de suite et à intégrer la sécurité dans la trajectoire de reprise.