Préparation aux migrations de base de données pour les applications auto-hébergées : pouvez-vous revenir en arrière en toute sécurité ?
Utilisez cette checklist de retour arrière de migration de base de données avant de mettre à jour une application auto-hébergée. Distinguez le retour arrière du code de la récupération de la base de données, évaluez la compatibilité et les verrous, vérifiez les sauvegardes et définissez les décisions de récupération avant le déploiement.

Pourquoi le retour arrière de l’application et celui de la base de données sont différents
Remplacer un nouveau conteneur applicatif par l’image précédente peut être rapide. Il s’agit d’un retour arrière du code. Cela ne rétablit pas automatiquement la structure et le contenu de la base de données attendus par la version antérieure.
Une migration de base de données peut ajouter des tables, renommer des colonnes, transformer des valeurs stockées, créer des index, renforcer des contraintes, supprimer des données ou lancer un travail qui se poursuit après le déploiement. Lorsqu’une migration a été validée, un ROLLBACK au niveau de la transaction n’est plus disponible pour ce travail validé. Une récupération sûre peut plutôt nécessiter une restauration des données, une réparation des données ou la mise en œuvre d’un correctif ultérieur.
Considérez la version de l’application et la modification de la base de données comme deux objets de déploiement liés mais distincts. L’approbation doit dépendre de la capacité de l’ancienne application à fonctionner en toute sécurité avec l’état de la base de données après migration, et non simplement de la disponibilité d’une image de conteneur antérieure.
- Question relative au retour arrière du code : l’ancienne version de l’application peut-elle être démarrée et remise en service ?
- Question relative à la récupération de la base de données : le schéma précédent et les données métier requises peuvent-ils être restaurés ou reconstruits sans perte inacceptable ?
- Question de compatibilité : l’ancien code, le nouveau code et la base de données modifiée peuvent-ils coexister pendant la transition planifiée ?
- Règle de décision : ne décrivez pas une version comme réversible tant que les chemins relatifs au code et à la base de données n’ont pas tous deux été examinés.

Recensez chaque modification affectant la base de données avant l’approbation
Établissez une cartographie des modifications à partir des notes de version de l’application, des fichiers de migration, des scripts de déploiement et des commandes de base de données. Ne vous fiez pas à une étiquette telle que « migration automatique » : identifiez ce que cette automatisation modifie réellement et à quel moment elle s’exécute.
Classez chaque opération selon son effet sur le schéma, les données, la disponibilité et la réversibilité. L’objectif n’est pas de prédire chaque détail d’implémentation. Il est de révéler les opérations qui modifient la stratégie de récupération ou exigent des contrôles opérationnels.
Pour les déploiements conteneurisés, identifiez également l’emplacement des données persistantes de la base de données. Les volumes Docker Compose sont des stockages persistants gérés par le moteur de conteneurs ; le volume de la base de données, tout service de base de données externe et la source de sauvegarde doivent donc être clairement identifiés. Recréer une charge de travail applicative ne prouve pas que la base de données a été préservée.
- Schéma : nouvelles tables ou tables supprimées, colonnes, types, index, clés étrangères, valeurs par défaut et contraintes.
- Transformation des données : remplissages rétrospectifs, conversions de valeurs, déduplication, modifications du chiffrement, réécriture d’identifiants et suppressions.
- Performances et verrous : réécritures de tables, créations d’index, requêtes longues et opérations pouvant attendre d’autres transactions.
- Travail en arrière-plan : tâches en file d’attente, workers, tâches planifiées ou tâches au démarrage de l’application qui continuent de modifier des données après la migration de schéma.
- Dépendances : outils de reporting, intégrations, exports, vues, consommateurs d’API et scripts personnalisés pouvant dépendre de champs ou de valeurs existants.
- Métadonnées de migration : identifiant de migration, ordre d’exécution, outil ou framework, et présence ou non d’une opération inverse documentée pour chaque étape.

Vérifiez explicitement la compatibilité ascendante et descendante
Un déploiement sûr dépend souvent d’une fenêtre de compatibilité : une période durant laquelle les versions précédente et nouvelle de l’application peuvent utiliser le même état de base de données. Sans cette fenêtre, un retour arrière du code après migration peut échouer même si l’ancienne image démarre normalement.
Examinez séparément les comportements de lecture et d’écriture. L’ancien code peut tolérer une nouvelle colonne nullable, mais échouer si une colonne qu’il écrit a été supprimée, renommée, rendue obligatoire ou a changé de signification. Le nouveau code peut démarrer avant la fin d’un remplissage rétrospectif uniquement s’il peut traiter correctement les anciennes et nouvelles représentations.
Faites de la compatibilité une décision documentée plutôt qu’une hypothèse. Si l’ancien code n’est pas compatible avec la base de données migrée, le plan de récupération doit privilégier une restauration, une réparation des données ou un correctif ultérieur plutôt qu’un simple retour arrière du code.
- Ancien code avec schéma étendu : peut-il ignorer les tables, colonnes et index ajoutés ?
- Nouveau code avant la fin de la migration des données : peut-il lire à la fois les anciens et nouveaux formats de valeurs ?
- Ancien code après un remplissage rétrospectif : va-t-il écraser les données transformées ou créer des enregistrements dans un format obsolète ?
- Moment d’application des contraintes : une nouvelle contrainte NOT NULL, d’unicité ou de clé étrangère rejettera-t-elle les écritures faites par une ancienne version ?
- Consommateurs externes : les intégrations dépendent-elles d’un nom de colonne, d’un format de sortie, d’un identifiant ou d’un comportement d’API affecté par le changement ?
- Fonctionnement avec versions mixtes : si plusieurs workers de l’application sont redémarrés progressivement, le fonctionnement simultané de l’ancienne et de la nouvelle version est-il pris en charge ?
Signalez les opérations destructrices et les modifications sensibles aux verrous
Certaines modifications nécessitent un plan de récupération explicite parce qu’elles suppriment des informations, rendent invalides les anciennes hypothèses ou affectent la disponibilité. La suppression d’une colonne PostgreSQL peut également supprimer les index et contraintes de table associés à cette colonne ; des dépendances extérieures à la table, telles que des clés étrangères ou des vues, peuvent exiger des actions supplémentaires. Une modification destructrice ne doit jamais être approuvée uniquement parce qu’elle apparaît tard dans une séquence de migration.
Les effets des verrous sont tout aussi importants. Dans PostgreSQL, les exigences de verrouillage d’ALTER TABLE diffèrent selon la sous-commande, et ACCESS EXCLUSIVE est le comportement par défaut, sauf indication contraire de la documentation. Examinez les instructions exactes plutôt que de considérer toutes les opérations ALTER TABLE comme équivalentes.
La création d’index nécessite également un choix de déploiement. Une création d’index PostgreSQL standard bloque les écritures pendant son exécution. CREATE INDEX CONCURRENTLY évite de bloquer les insertions, mises à jour et suppressions concurrentes, mais ne peut pas s’exécuter dans un bloc de transaction, effectue des analyses supplémentaires de la table et attend la fin des transactions pertinentes. Cela modifie à la fois le calendrier et la gestion des échecs.
Les formes d’ALTER TABLE qui réécrivent une table et TRUNCATE doivent faire l’objet d’un examen renforcé en cas d’accès concurrent. PostgreSQL documente des réserves liées à MVCC pour ces opérations, y compris des cas où des instantanés concurrents peuvent voir une vue vide ou incohérente après la validation.
- Destructrices : DROP COLUMN, DROP TABLE, TRUNCATE, remplissages rétrospectifs par suppression, conversions irréversibles de valeurs et remplacement d’identifiants.
- Rupture de compatibilité : renommage ou suppression d’un champ utilisé par l’ancien code, renforcement d’une contrainte et modification de la signification des valeurs stockées.
- Sensibles à la disponibilité : réécritures de tables, opérations ALTER TABLE nécessitant beaucoup de verrous et créations d’index standard sur des tables activement écrites.
- Étapes hors transaction unique : création d’index concurrente et travail en arrière-plan ayant lieu hors d’une même frontière transactionnelle.
- Réponse requise : nommez la méthode de récupération exacte pour chaque opération signalée avant le déploiement.
Privilégiez l’approche étendre, migrer, réduire lorsque l’application la prend en charge
Pour les changements importants, utilisez un modèle étendre–migrer–réduire lorsque l’application et les recommandations de son éditeur le prennent en charge. Cette approche sépare le travail de compatibilité du nettoyage destructeur, ce qui laisse la possibilité de valider et de revenir en arrière sur le code avant d’introduire des changements irréversibles.
Étendre consiste à ajouter de nouvelles structures sans supprimer les anciennes : par exemple, un nouveau champ nullable, une table ou un index. Migrer consiste à remplir les données rétrospectivement et à apprendre à la nouvelle version de l’application à lire et écrire la représentation compatible. Réduire consiste à supprimer les structures obsolètes uniquement après la fin de la fenêtre de compatibilité et la validation complète.
N’imposez pas ce modèle à une application dont le chemin de migration fourni ne prend pas en charge des versions par étapes. Dans ce cas, documentez la séquence exigée par l’éditeur, testez-la fidèlement et choisissez un plan de maintenance et de récupération approprié. Le principe utile est la séparation des risques, et non une réécriture artificielle de migrations tierces.
- Étendre : ajoutez la nouvelle structure et confirmez que l’ancien code continue de fonctionner.
- Déployer un code compatible : assurez-vous que le nouveau code gère les deux représentations lorsque c’est nécessaire.
- Migrer : exécutez les remplissages rétrospectifs par lots observables lorsque l’application prend en charge cette approche.
- Valider : comparez les volumes, les enregistrements requis, les autorisations, les intégrations et les flux de travail essentiels.
- Réduire : supprimez les champs ou formats hérités uniquement après la fermeture intentionnelle de la fenêtre de retour arrière.
- Consignez le point de non-retour : indiquez précisément à quel moment un simple retour arrière du code n’est plus sûr.
Collectez des preuves de déploiement, pas seulement un statut de sauvegarde
Une sauvegarde n’est utile que si sa méthode, sa couverture, son emplacement et son processus de restauration sont compris. PostgreSQL distingue les exports SQL, les sauvegardes du système de fichiers et l’archivage continu ; chacun présente des forces et limites différentes. Consignez la méthode qui protège cette modification au lieu d’utiliser l’affirmation générique « sauvegarde terminée ».
Un export logique PostgreSQL est un instantané cohérent en interne à partir du moment où pg_dump commence, mais les opérations nécessitant un verrou exclusif, y compris la plupart des formes d’ALTER TABLE, constituent des exceptions à son comportement par ailleurs non bloquant. Confirmez que le moment et la méthode de sauvegarde sont compatibles avec les exigences de verrouillage et de récupération de la migration.
La récupération à un instant donné n’est pas une promesse générique. Avec PostgreSQL, elle exige une sauvegarde physique antérieure appropriée et des journaux d’écriture anticipée archivés couvrant l’heure cible. Si ces prérequis sont absents, ne présentez pas la récupération à un instant donné comme une option disponible.
Airbip fournit des sauvegardes quotidiennes, hebdomadaires et mensuelles configurables pour les déploiements d’applications. Les équipes doivent néanmoins vérifier le périmètre, la configuration de rétention, la couverture de la base de données et la procédure de restauration applicables à leur propre instance avant de dépendre de ces sauvegardes pour une décision de migration.
- Identité de la sauvegarde : méthode, heure de fin, périmètre, emplacement de stockage et personne l’ayant vérifiée.
- Confiance dans la restauration : test de restauration récent, étapes estimées, identifiants requis, environnement cible et limitations connues.
- Preuves de migration : version exacte de la release ou référence d’image, identifiants de migration, heures de début et de fin, journaux et erreurs.
- Contrôles de référence : consignez les volumes importants, des enregistrements représentatifs, les flux de travail critiques et l’état des intégrations avant la modification.
- Contrôles après modification : consignez les mêmes contrôles après la migration et définissez les écarts acceptables.
- Seuil de récupération : décidez de la durée maximale d’interruption et de l’exposition à la perte de données acceptables avant de commencer.
Déterminez si une fenêtre de maintenance ou une restriction temporaire d’écriture est nécessaire
Une fenêtre de maintenance est justifiée lorsque la migration peut bloquer les écritures, créer des états mixtes incompatibles, prendre un temps incertain ou exiger une restauration ne pouvant pas fusionner en toute sécurité les modifications ultérieures des utilisateurs. Une restriction temporaire d’écriture peut être suffisante lorsque les lectures restent sûres mais que les écritures entreraient en conflit avec un remplissage rétrospectif, une modification de schéma ou un éventuel retour arrière.
Fondez la décision sur les opérations réelles et l’impact métier. Par exemple, une création d’index PostgreSQL normale bloque les écritures, tandis qu’une création d’index concurrente évite ce blocage spécifique des écritures, mais présente des caractéristiques opérationnelles de plus longue durée et ne peut pas partager une frontière transactionnelle normale. Aucune de ces options n’est automatiquement plus sûre sans tenir compte de la charge de travail, du calendrier et de la récupération.
Définissez ce que les utilisateurs verront et ce que les opérateurs feront. Une restriction d’écriture peut consister à suspendre les workers en arrière-plan, désactiver les imports planifiés, placer une application en mode maintenance pris en charge par l’éditeur ou rejeter temporairement les requêtes d’écriture. Veillez à ce que les intégrations et les administrateurs reçoivent la même consigne ; sans cela, ils pourraient créer des données qui compliqueraient la récupération.
- Utilisez une fenêtre de maintenance complète lorsque les modifications de schéma ou la restauration rendent les écritures concurrentes dangereuses.
- Utilisez une restriction d’écriture ciblée lorsque l’accès en lecture peut continuer sans risque et que l’application prend en charge ce mode.
- Suspendez ou prenez en compte les workers en arrière-plan, les imports, les webhooks et les tâches planifiées.
- Définissez une heure de début, une durée attendue, un point de décision pour la prolongation et un canal de communication avec les utilisateurs.
- Confirmez comment le travail mis en file d’attente sera repris, dédupliqué ou réconcilié après le déploiement ou la récupération.
- Arrêtez-vous si les verrous, la durée ou les taux d’erreur dépassent le seuil approuvé.
Choisissez le chemin de récupération avant le déploiement
La récupération est un arbre de décision, et non un unique bouton de retour arrière. Préapprouvez les conditions dans lesquelles l’équipe reviendra en arrière sur le code applicatif, restaurera les données, réparera un ensemble limité d’enregistrements ou poursuivra avec un correctif ultérieur. Désignez qui peut autoriser chaque action, particulièrement une restauration susceptible d’écarter des écritures légitimes effectuées après le point de sauvegarde choisi.
Un retour arrière du code n’est approprié que si la compatibilité a été confirmée et que la migration n’a pas créé un état de base de données dangereux pour l’ancienne version. Une restauration est appropriée lorsque l’état des données lui-même doit revenir à un point connu, mais elle exige un traitement attentif des écritures survenues après la sauvegarde. La réparation des données peut convenir à une erreur limitée, entièrement comprise et vérifiable. Un correctif ultérieur est souvent plus sûr lorsque la restauration ferait perdre davantage d’activité métier valide que la correction du défaut.
Le comportement du framework compte également. Par exemple, Django identifie comme irréversibles les étapes RunPython sans reverse_code et les étapes RunSQL sans reverse_sql. Le comportement transactionnel des migrations Django varie aussi selon le moteur de base de données : sa gestion par défaut diffère entre les moteurs avec transactions DDL, comme PostgreSQL et SQLite, et les moteurs tels que MySQL et Oracle. Consultez les recommandations du framework de migration de l’application et celles spécifiques à la base de données avant de supposer qu’une inversion est disponible.
- Retour arrière du code : précisez la version antérieure compatible et les contrôles requis avant de rediriger le trafic.
- Restauration : précisez le point de récupération, la méthode, l’interruption attendue, les implications de perte de données et le responsable de la réconciliation.
- Réparation des données : précisez les enregistrements concernés, le script de réparation, la piste d’audit, la requête de validation et la méthode d’inversion de la réparation elle-même.
- Correctif ultérieur : précisez l’état intermédiaire sûr, le responsable, le chemin d’escalade et les contrôles d’impact utilisateur.
- Autorité : désignez l’opérateur technique, le responsable métier des données et le décideur final pour chaque option de récupération.
- Communications : préparez des messages internes et destinés aux utilisateurs pour une maintenance prolongée, une réconciliation des données ou une remise en service.
Questions fréquentes
Puis-je annuler une migration de base de données en revenant en arrière sur le conteneur applicatif ?
Pas nécessairement. Revenir à une image applicative plus ancienne modifie le code, mais pas le schéma ni les données de base de données déjà validés. N’utilisez le retour arrière du code qu’après avoir confirmé que l’ancienne version est compatible avec l’état de la base de données après migration.
Que doit inclure une checklist de retour arrière de migration de base de données ?
Incluez les modifications exactes du schéma et des données, la réversibilité de la migration, la compatibilité entre ancien et nouveau code, les risques de verrouillage et d’interruption, la méthode et le périmètre de sauvegarde, les preuves de test de restauration, la validation avant et après modification, un plan de contrôle des écritures, les options de récupération et les décideurs désignés.
Dans quels cas une sauvegarde ne suffit-elle pas à assurer un retour arrière sûr ?
Une sauvegarde seule est insuffisante lorsque l’équipe ne sait pas si elle inclut la base de données, si elle peut être restaurée, quel instant elle représente ou comment les modifications des utilisateurs après la sauvegarde seront traitées. Un plan de restauration exige à la fois des preuves et une décision métier sur la perte de données acceptable.
CREATE INDEX CONCURRENTLY est-il toujours la bonne option dans PostgreSQL ?
Non. Cette commande évite de bloquer les insertions, mises à jour et suppressions concurrentes, mais elle ne peut pas s’exécuter dans un bloc de transaction, utilise des analyses supplémentaires de la table et attend les transactions pertinentes. Choisissez-la selon la charge de travail, l’outillage de déploiement, la durée et la gestion des échecs.
Quand faut-il utiliser une fenêtre de maintenance pour une migration de base de données ?
Utilisez-en une lorsque des opérations peuvent bloquer les écritures, lorsque les anciennes et nouvelles versions de l’application ne peuvent pas coexister en toute sécurité, lorsque l’activité en arrière-plan compliquerait la récupération ou lorsqu’une restauration serait la réponse probable à un échec. Une restriction temporaire d’écriture peut suffire pour des changements à impact moindre lorsque les lectures peuvent continuer sans risque.
Quel est le rôle d’Airbip dans la préparation aux migrations de base de données ?
Airbip gère les déploiements d’applications basés sur Docker et propose des sauvegardes quotidiennes, hebdomadaires et mensuelles configurables. La préparation aux migrations reste une responsabilité opérationnelle partagée : l’équipe doit vérifier ce qui est sauvegardé, tester la restauration lorsque cela est approprié, comprendre le comportement de migration de l’application et approuver les décisions relatives aux données et à la récupération.
Sources et lectures complémentaires
- PostgreSQL transactions — PostgreSQL Global Development Group
- PostgreSQL ALTER TABLE — PostgreSQL Global Development Group
- PostgreSQL CREATE INDEX — PostgreSQL Global Development Group
- PostgreSQL backup and restore — PostgreSQL Global Development Group
- PostgreSQL SQL dump — PostgreSQL Global Development Group
- PostgreSQL write-ahead logging — PostgreSQL Global Development Group
- PostgreSQL MVCC caveats — PostgreSQL Global Development Group
- Django migration operations — Django Software Foundation
- Django migrations — Django Software Foundation
- Docker Compose volume reference — Docker