Une migration sans interruption peut-elle rester réversible?
Planifiez une migration sans interruption avec routage Strangler, doubles écritures durables, réconciliation et bascule réversible.

Une migration sans interruption n'est possible que si l'ancien système reste une destination valide jusqu'à ce que le nouveau ait prouvé qu'il peut prendre le relais. Cela paraît évident, pourtant beaucoup de plans détruisent discrètement cette possibilité. Ils copient les données, déploient le remplaçant, prévoient une fenêtre de maintenance et appellent l'arrêt «la bascule». Cet arrêt n'est pas une loi naturelle. Il vient du couplage de quatre actions distinctes: changer la route, changer le composant qui écrit, transférer l'autorité sur les données et supprimer l'ancien chemin.
Une conception plus sûre sépare ces actions et rend chacune observable et réversible. Les requêtes passent par un point de routage. Les écritures ont des identités stables et peuvent être rejouées. Le chargement initial occupe une position définie dans le flux de changements. La réconciliation compare le sens métier, pas la forme des octets. Le dernier changement de route devient alors une petite modification de configuration plutôt qu'un saut dans le vide.
Cela ne veut pas dire qu'un utilisateur ne verra jamais d'erreur. Un système peut rester disponible alors qu'une requête échoue pour les mêmes raisons qu'avant la migration. La promesse est plus étroite et plus utile: la migration n'impose aucune période pendant laquelle le service refuse tout travail, et les opérateurs peuvent renvoyer le trafic sans reconstruire la base de données de la veille.
L'absence d'interruption dépend du routage
L'application reste disponible si chaque requête conserve une destination valide pendant toute la migration. La réplication aide, mais elle ne suffit pas. Si les clients se connectent directement au serveur à remplacer, la décision de routage vit dans des centaines de clients et la bascule vous échappe.
Placez un point de décision contrôlé devant les deux implémentations. Il peut s'agir d'une passerelle API, d'un proxy inverse, d'une règle d'équilibrage, d'une affectation de consommateur ou d'un adaptateur dans le processus existant. La technologie compte moins que le contrat: les opérateurs doivent pouvoir changer la destination d'une tranche précise sans redéployer tous les appelants.
Choisissez cette tranche selon une frontière métier stable. Routez la consultation d'un compte séparément de sa modification, l'export d'une facture séparément de sa création, ou un locataire séparément des autres. Ne découpez pas selon le fichier contrôleur le plus facile à remplacer. Une route qui mélange lectures, écritures, tâches planifiées et rappels peut afficher un canari au vert tandis qu'un chemin invisible continue de modifier les anciennes données.
Un enregistrement de route minimal doit être assez banal pour être relu pendant un incident:
{
"capability": "invoice.read",
"cohort": "tenant-042",
"destination": "new",
"fallback": "old",
"revision": 17,
"changed_by": "change-1842"
}
capability nomme le comportement, pas une URL. cohort limite l'exposition. fallback indique où le routeur peut envoyer une requête si le nouveau côté est indisponible. La révision révèle les modifications concurrentes et la référence explique au responsable d'incident pourquoi la route a bougé. Conservez cet enregistrement dans un système avec historique et faites garder au routeur la dernière configuration valide si le plan de contrôle disparaît.
Les contrôles de santé doivent tester la capacité routée. Un processus qui répond à /health peut manquer d'une migration de base, d'une clé de déchiffrement ou d'une dépendance joignable. Exécutez une petite lecture ou une opération synthétique qui traverse la même chaîne que le trafic réel, avec des données réservées. Restez prudent avec le repli automatique des écritures. Refaire une lecture sur l'ancien côté est souvent sans danger; rejouer une écriture acceptée peut créer une seconde commande, un second paiement ou un second dossier.
Le point Strangler doit couvrir toutes les entrées
Le routage Strangler ne fonctionne que si son point d'interception couvre toutes les entrées d'une capacité. La description du motif Strangler Fig par Martin Fowler insiste sur un remplacement progressif autour de l'ancien système. Les équipes retiennent souvent «progressif» et oublient «autour». Si un traitement nocturne, un client de bureau, un dépôt de fichier ou une file contourne ce point, deux implémentations peuvent agir sans politique commune.
Recensez les entrées à partir des preuves d'exécution, pas du schéma d'architecture. Examinez journaux d'accès, liaisons de files, planificateurs, flux de pare-feu, langage de contrôle des traitements, appels de procédures stockées et rappels sortants qui reviennent ensuite comme travail entrant. Un ancien système expose souvent la même opération par HTTP, transaction terminal et fichier importé après minuit. Traitez-les comme une capacité et plusieurs adaptateurs.
Le point d'interception doit normaliser identité et contexte avant l'envoi. Les deux côtés ont besoin du même identifiant de requête, acteur, locataire, résultat d'autorisation, délai et identifiant d'idempotence. Si chaque implémentation les calcule seule, la réconciliation accusera la logique métier pour des écarts créés en bordure. Conservez le corps original pour l'audit lorsque la politique le permet, mais transmettez aux deux chemins une enveloppe canonique versionnée.
N'utilisez pas d'abord un routage aléatoire par pourcentage pour un travail avec état. Un canari de dix pour cent peut envoyer la première étape d'un processus au nouveau côté et la suivante à l'ancien. Préférez une clé déterministe: locataire, compte, dossier ou identifiant de processus. Le routeur doit donner la même réponse pour cette clé jusqu'à modification de la règle de cohorte.
L'authentification est une autre entrée. Si l'ancien système crée des sessions que le nouveau ne sait pas vérifier, la première requête routée force une reconnexion. Validez la session au point d'interception et transmettez une assertion signée de courte durée, ou rendez les deux côtés compatibles avec un format de session partagé pendant la coexistence. Ne migrez pas les hachages de mots de passe en imposant une réinitialisation, sauf si l'entreprise accepte consciemment cette perturbation.
Rendez enfin l'évaluation de route visible dans chaque trace et chaque journal. Enregistrez révision de règle, destination choisie, décision de repli et clé de cohorte. Si un utilisateur signale que la facture d'hier diffère de celle d'aujourd'hui, vous devez savoir quelle implémentation a servi chaque requête. Un tableau de bord limité aux pourcentages agrégés ne répondra pas.
Les doubles écritures exigent une intention durable
La forme sûre de double écriture enregistre une intention métier durable, puis des workers indépendants l'appliquent à chaque modèle de données. La forme dangereuse fait appeler la base A puis la base B par le thread de requête en espérant deux succès. Une faille est inévitable: le premier commit réussit, le second expire, et l'appelant ignore si une nouvelle tentative dupliquera le travail.
Faites valider à l'autorité actuelle le changement métier et un événement d'outbox dans la même transaction locale. Un relais publie l'événement et un consommateur applique une projection idempotente au nouveau stockage. Au début, l'ancien stockage reste l'autorité même si la nouvelle projection accuse quelques secondes de retard. Après le déplacement de la route, le sens peut s'inverser pour garder le retour possible.
L'enveloppe d'écriture doit permettre de rejeter les doublons et de détecter un mauvais ordre:
{
"event_id": "01J7M6R2K8N4T3Q9V5X1",
"aggregate_type": "invoice",
"aggregate_id": "inv-90318",
"aggregate_version": 44,
"operation": "invoice.adjusted",
"occurred_at": "2026-08-14T10:42:31Z",
"payload": {"line_id": "ln-8", "amount_minor": 1250}
}
Le consommateur stocke event_id dans une table d'événements traités avec contrainte d'unicité. Il applique la version 44 après la 43, ou met l'événement de côté jusqu'à l'arrivée de la version manquante. La charge utile utilise des unités métier, comme les unités monétaires mineures, plutôt que des chaînes formatées. Une livraison répétée réussie renvoie le résultat précédent sans refaire l'opération.
La documentation Microsoft sur les nouvelles tentatives énonce clairement le risque: un service peut terminer le travail puis perdre la réponse, si bien qu'une tentative répète une opération non idempotente. Les migrations créent souvent ce cas lorsque les relais redémarrent et que les chemins réseau changent. L'identifiant d'idempotence n'est pas un simple confort d'API. Il prouve que deux livraisons portent une intention unique.
Certaines écritures ne peuvent pas être rejouées sans risque, surtout un appel à un tiers sans idempotence. Gardez cet effet derrière l'autorité existante pendant la coexistence. Répliquez l'état obtenu, pas la commande qui l'a produit. Envoyer la même instruction de paiement depuis les deux systèmes revient à émettre deux paiements.
Surveillez l'âge de l'outbox, pas seulement son nombre de lignes. Une petite file avec un événement bloqué depuis six heures peut être pire qu'une grande file qui se vide normalement. Exposez le plus ancien événement non publié, le plus ancien événement non appliqué par type d'agrégat, le nombre de tentatives, la cause de mise à l'écart et le trou de version. Ces signaux montrent si les données de retour sont réellement à jour.
Le chargement initial doit rejoindre le flux vivant
Un chargement initial n'est fini que lorsque son instantané a rejoint le flux de changements à une position connue. Copier toutes les lignes pendant que la production continue poursuit une cible mobile. Si le copieur lit un compte avant une mise à jour puis l'écrit après son application par le consommateur, l'ancien instantané peut écraser un état plus récent.
Deux méthodes sont saines. Prenez un instantané cohérent lié à une position du journal, chargez-le, puis appliquez les changements postérieurs. Ou conditionnez chaque upsert du chargement à la version source pour qu'il ne remplace jamais une projection plus récente. La syntaxe des outils de capture varie, mais l'invariant reste identique: tout enregistrement copié et tout événement vivant doivent être ordonnables.
La réplication logique de PostgreSQL montre l'aide et les limites. Sa documentation indique que les changements suivent l'instantané initial dans l'ordre du producteur au sein d'un abonnement. Elle avertit aussi que les définitions de schéma et le DDL ne sont pas répliqués dans les versions courantes, et que l'état des séquences a longtemps demandé un traitement séparé avant bascule. Le manuel de votre version exacte appartient au runbook. «La réplication est à jour» ne prouve pas que la cible peut accepter des écritures.
Réglez le débit du chargement sur la latence de production plutôt que sur un nombre fixe de lignes par seconde. Lisez par plages de clé primaire, mémorisez la plage terminée et la position, et rendez chaque lot redémarrable. Les grosses transactions retiennent les journaux, prolongent les verrous et masquent la progression. Les très petites gaspillent du temps système. Mesurez l'effet sur la source et choisissez un lot qui finit et se rejoue confortablement dans vos limites.
Les transformations ont besoin d'un stockage explicite des erreurs. Si un ancien statut contient une valeur refusée par la nouvelle énumération, ne la convertissez pas silencieusement en UNKNOWN. Enregistrez clé et version source, version du transformateur, valeur brute et erreur. Le responsable métier décide alors si la valeur correspond à un état existant, exige un nouvel état ou révèle une ancienne corruption.
Ne rechargez jamais de totaux dérivés sans désigner qui les recalcule. Si le nouveau système déduit le solde d'une facture de ses écritures et l'ancien conserve une colonne de solde modifiable, comparez écritures et solde final, mais ne copiez pas éternellement cette colonne. Sinon, deux autorités survivent dans le nouveau schéma.
La réconciliation compare des invariants
La réconciliation doit prouver que les deux systèmes font les mêmes affirmations métier malgré des schémas différents. Comptages et sommes de contrôle détectent des données absentes, mais ne constituent pas le principal test après une refonte. Un modèle Postgres normalisé n'a pas les mêmes lignes qu'un enregistrement COBOL, et un client TypeScript ne sérialise pas les champs comme un programme de bureau.
Commencez par les invariants déjà utilisés par l'entreprise: chaque écriture publiée appartient à un compte, débits et crédits s'équilibrent dans une frontière comptable, une facture égale ses lignes plus la taxe, un dossier fermé possède un événement de clôture et une référence externe reste unique. Exécutez chaque invariant des deux côtés et comparez par identifiant métier stable.
Pour les champs censés correspondre, ne canonisez que les différences sans sens métier. Uniformisez la précision des horodatages, la forme Unicode, le traitement des chaînes vides et valeurs nulles selon l'ancien comportement, et l'argent en unités mineures entières. Ne passez pas des identifiants en minuscules et n'arrondissez pas pour verdir un rapport. Toute règle peut cacher un défaut, elle doit donc être versionnée et relue.
Une requête de comparaison utile renvoie les écarts, pas un nombre de réussites:
SELECT account_id, old_balance_minor, new_balance_minor,
old_balance_minor - new_balance_minor AS delta_minor
FROM migration_account_balance
WHERE old_balance_minor <> new_balance_minor
ORDER BY ABS(old_balance_minor - new_balance_minor) DESC;
La forme de sortie compte: l'opérateur a besoin de l'identifiant métier, des deux valeurs et de l'écart. Stockez identifiant d'exécution, positions source et cible, version de requête, heures de début et de fin, nombre d'écarts et échantillon limité. Sans positions, un rapport n'est pas reproductible, car les bases continuent de changer.
Classez les écarts par cause. Un trou de transport signifie qu'un événement n'est jamais arrivé. Un trou d'ordre indique une arrivée trop tôt ou trop tard. Un défaut de transformation produit le mauvais état cible depuis la bonne source. Les écarts attendus viennent de changements voulus, comme le retrait d'espaces finaux. Tout écart inexpliqué bloque l'élargissement, même en petit nombre.
N'exigez pas zéro écart universel lorsque le temps change la réponse. Un devis expirant ou un stock vivant peut différer entre deux lectures successives. Figez l'horloge concernée, comparez aux mêmes positions de journal ou vérifiez une tolérance métier approuvée. Un «assez proche» choisi par l'équipe de migration n'est pas un critère de réception.
Les lectures fantômes révèlent le comportement
Les lectures fantômes font traiter de vraies requêtes par le nouveau système tandis que l'ancienne réponse revient au client. Elles trouvent les défauts sémantiques ignorés par les contrôles de données: tri par défaut, cas limites d'autorisation, arrondi, format local, enregistrements absents et erreurs différentes. Comme le nouveau résultat est jeté, ce procédé ne convient qu'aux opérations sans effet.
Dupliquez la requête normalisée au point de routage avec un délai strict plus court que le budget utilisateur. Une lecture fantôme lente ne doit jamais retarder la réponse d'autorité. Retirez ou substituez les secrets inutiles au nouveau chemin et marquez la requête afin qu'aucun code aval n'envoie de courriel, ne modifie un cache, ne prolonge une session ni ne produise un appel facturable.
Comparez le sens structuré, pas les octets. Ignorez identifiants de trace et horodatages générés. Comparez classe d'état, collections ordonnées ou non selon le contrat, décision d'autorisation, champs choisis, catégorie d'erreur et totaux métier. Gardez un exemple expurgé par nouvelle signature d'écart, pas chaque réponse. Le stockage de comparaison ne doit pas devenir une seconde copie de données sensibles.
Exécuter une écriture puis annuler la transaction est généralement dangereux. Appels externes, allocation de séquence, publication en file et déclencheurs peuvent échapper à la transaction. Validez l'écriture avec du trafic enregistré dans un banc isolé, ou exécutez sa logique de décision pure sur un instantané en neutralisant l'adaptateur de commit. Dites exactement ce qui a été testé.
Les comparaisons de performance demandent la même rigueur. Une requête fantôme exécutée après l'ancienne peut profiter d'un cache chaud; l'exécution parallèle ajoute une charge qu'aucun système ne voit seul. Mesurez latence et ressources des deux côtés, mais ne déclarez pas de gagnant avant de contrôler cache, mélange de requêtes et charge fantôme.
Le bon critère de sortie combine couverture et comportement propre. Suivez les opérations, rôles d'autorisation, formes de données et chemins d'erreur exercés. Dix millions de recherches de compte usuelles ne prouvent pas le rare chemin d'annulation. Routez une cohorte seulement après avoir observé ou volontairement testé son ensemble réel de comportements.
La bascule est une machine à états
Une bascule réversible déplace une capacité entre des états nommés, avec des transitions gardées. Une entrée au calendrier peut autoriser la transition, mais l'heure ne décide pas de sa sûreté. Les opérateurs doivent voir sur une page l'autorité, la route, le sens de réplication, le retard et l'action de retour.
Utilisez des états qui décrivent des faits:
old_only: l'ancien côté sert et écrit; le nouveau peut être vide.old_authority: les deux reçoivent les données actuelles; les utilisateurs atteignent l'ancien.new_canary: une cohorte déterministe atteint le nouveau; les écritures anciennes restent à jour.new_primary: tout le trafic éligible atteint le nouveau; l'ancien reste prêt au retour.new_only: la fenêtre de retour est fermée et les anciennes mutations sont désactivées.
Chaque transition exige des gardes lisibles par machine. Passer à new_canary peut exiger zéro écart inexpliqué, aucun événement non appliqué au-delà du budget, une couverture fantôme de toutes les opérations critiques et un retour de route testé. new_primary ajoute réserve de capacité, propriété des tâches, préparation du support et confirmation que les entrées non HTTP suivent la même autorité.
Gardez la commande de transition petite et idempotente. Elle met à jour une route versionnée; elle ne doit pas déployer du code, changer le schéma, vider les files et redémarrer les workers. Si cinq actions doivent arriver dans la même minute, l'une sera en retard et le retour restera ambigu.
Séparez arrêt et retour. Un arrêt gèle l'élargissement tout en gardant les rôles actuels. Un retour renvoie le trafic à l'ancien parce qu'une garde a échoué. Une réparation corrige les données après compréhension du défaut. Recopier automatiquement la cible vers la source pendant une alarme peut propager la corruption plus vite que le diagnostic.
Répétez la transition inverse en production avant la bascule générale. Envoyez une cohorte au nouveau, créez et modifiez des données représentatives, renvoyez-la à l'ancien et confirmez que ces données restent exactes et accessibles. Un document de retour qui n'a jamais déplacé d'état réel reste une théorie.
Le retour expire quand l'ancien cesse d'apprendre
L'ancien système reste une cible de retour uniquement s'il reçoit tous les changements nécessaires pour reprendre l'autorité. Des serveurs allumés ne servent à rien si leur base est en retard dès la première écriture nouvelle. Définissez la fenêtre en termes de données: opérations répliquées en arrière, retard acceptable et changements impossibles à représenter dans l'ancien modèle.
La réplication inverse se complique lorsque la nouvelle architecture autorise des états inexprimables dans l'ancien schéma. Retardez ces fonctions pendant la coexistence ou ajoutez une représentation compatible avant la bascule. Si le nouveau système permet plusieurs ajustements là où l'ancien n'a qu'un montant, aucun retour n'est promis après le second ajustement si l'ancien chemin ne peut pas le conserver.
Employez une séquence d'expansion puis de contraction du schéma. Ajoutez champs et lecteurs tolérant les deux formes. Remplissez la nouvelle. Changez les écrivains. Observez. Retirez l'ancienne forme après fermeture de la fenêtre. Changements destructifs, valeurs d'énumération réutilisées et champs raccourcis effacent le chemin de retour alors que le routage paraît encore réversible.
Une tâche planifiée doit avoir un seul propriétaire. Le trafic interactif peut atteindre le nouveau pendant que deux planificateurs produisent des relevés ou ferment des dossiers. Donnez à chaque tâche un bail ou indicateur d'autorité gouverné par le même état, et notez l'implémentation ayant réclamé chaque exécution. Au retour, transférez le bail avant la route si la tâche modifie des données lues par l'ancien chemin.
CodeHero intègre ce contrat de coexistence à la réécriture: le nouveau système en Go, Rust ou TypeScript est comparé au trafic de production enregistré par un banc de parité, et le projet est livré en moins de 30 jours. Cette promesse courte ne remplace ni les gardes de réception du client ni sa politique de retour; elle empêche de cacher ces décisions dans un long programme.
Fixez la condition explicite qui termine la réversibilité. Ce peut être le premier état réservé au nouveau, la suppression de la réplication inverse, un changement destructif ou la fin de l'accord de support des deux côtés. Faites-la approuver par le responsable. Sans point nommé, l'équipe le découvrira pendant l'incident, une fois le retour perdu.
Le dernier changement de route doit être banal
La bascule finale est sûre si elle ne change que la route par défaut d'une capacité dont les cohortes ont déjà tourné sur le nouveau côté. Code, données, tâches, contrôles d'accès, tableaux, consignes d'astreinte et mécanisme de retour sont déjà en production. Le risque restant tient à l'échelle, donc capacité et files comptent davantage que la correction fonctionnelle.
Avant le changement, capturez une décision avec révision exacte de route, positions de réplication, exécution de réconciliation, exceptions ouvertes, approbateur et seuil de retour. Vérifiez que l'ancien absorbe immédiatement toute la charge. Le réduire avant la fermeture économise peu et transforme une modification réversible en exercice de restauration de capacité.
Changez la route par étapes adaptées au domaine de panne. Un locataire révèle des problèmes propres à ses données. Une région révèle le placement des dépendances. Un pourcentage ne convient qu'avec une affinité de processus garantie. Attendez entre les étapes assez longtemps pour voir la tâche ou le rappel le plus lent, pas un graphique arbitraire de cinq minutes.
Surveillez ce que ressentent les utilisateurs: catégorie d'erreur, latence haute, âge des files, invariants violés, refus d'autorisation et contacts au support liés à la cohorte. Processeur et mémoire peuvent sembler calmes tandis que les factures disparaissent de la recherche à cause d'un consommateur bloqué. Associez chaque seuil à un signal nommé et une fenêtre d'observation.
Confiez la commande à un opérateur et la lecture des gardes à un autre. Le second doit pouvoir arrêter sans négocier dans le canal d'incident. Enregistrez automatiquement les deux décisions. Cette séparation attrape les tableaux périmés, les cohortes mal comprises et l'erreur habituelle qui prend le silence pour un accord.
Quand un seuil se déclenche, exécutez le retour de route testé et préservez les preuves. N'improvisez pas une correction en avant pendant que les erreurs s'accumulent. Une fois l'ancien côté stable, gelez si nécessaire les écritures cibles, enregistrez les positions et diagnostiquez. La réversibilité donne du temps seulement si les opérateurs l'utilisent.
Après fermeture, retirez volontairement le dispositif. Désactivez les anciens écrivains, révoquez les secrets, arrêtez les consommateurs inverses, archivez les preuves selon la politique et conservez l'historique de route. Un relais oublié peut ressusciter de vieilles données des mois plus tard. Un repli oublié peut envoyer quelques requêtes dans une application sans surveillance.
La migration réussit quand l'ancien système n'est plus nécessaire, pas quand la première requête atteint le nouveau. Jusque-là, traitez état de routage, position d'événement et preuves de réconciliation comme des données de production. Si l'un manque, la bascule dépend de la mémoire, précisément quand le signal d'astreinte rend la mémoire la moins fiable.
FAQ
Une migration peut-elle vraiment se faire sans interruption?
Oui, si chaque requête garde une destination valide pendant que route et autorité des données changent séparément. Cela signifie aucune panne globale imposée par la migration, pas une garantie pour chaque requête.
Qu'est-ce que le routage Strangler dans une migration?
Il place un point de décision contrôlé autour des anciennes et nouvelles implémentations, puis déplace capacités ou cohortes une par une. Il échoue si tâches, files, clients de bureau ou rappels le contournent.
Les doubles écritures sont-elles sûres pendant une migration?
Deux écritures directes dans le thread ne le sont pas, car l'une peut valider tandis que l'autre échoue. Validez changement métier et outbox ensemble, puis appliquez un événement idempotent à l'autre stockage.
Comment charger les données pendant que les utilisateurs écrivent?
Liez l'instantané à une position du flux puis appliquez les événements suivants dans l'ordre. Sinon, conditionnez chaque upsert à la version source pour empêcher des données anciennes d'écraser un événement récent.
Que doit comparer une réconciliation de migration?
Comparez invariants métier et identifiants stables, pas les lignes brutes. Incluez les deux valeurs, l'écart, les positions, la version de réconciliation et les preuves nécessaires pour reproduire chaque différence.
Quand les lectures fantômes sont-elles sûres?
Elles le sont pour les opérations sans effet, avec un délai propre qui ne retarde pas la réponse utilisateur. Marquez-les pour interdire messages, changements de session, événements et appels facturables en aval.
Quelle part du trafic donner à un canari?
Commencez par une cohorte métier déterministe plutôt qu'un pourcentage aléatoire. Elle doit être petite à inverser, mais assez riche pour exercer processus complets, rôles, tâches et rappels.
Qu'est-ce qui rend une bascule réversible?
L'ancien côté doit rester actuel, capable et prêt à reprendre toute la charge. Il faut un flux inverse, des schémas compatibles, un seul propriétaire par tâche et un retour testé avec des données réelles.
Quand fermer la fenêtre de retour?
Fermez-la à une frontière explicite et approuvée, comme le premier état réservé au nouveau ou un changement de schéma destructif. Quelques heures calmes ne suffisent pas.
Que faire après la bascule finale?
Désactivez les anciens écrivains, révoquez les accès, arrêtez les consommateurs inverses, gardez les preuves et retirez les replis. L'ancienne application est retirée quand aucun chemin pris en charge ne peut y écrire ou y renvoyer du travail.