Automatiser les migrations de bases de données avec Flyway ou Liquibase dans un projet Spring Boot : Stratégies et pièges
Dans un projet Spring Boot, l’automatisation des migrations de base de données garantit la reproductibilité des environnements, réduit le risque d’erreurs manuelles et facilite la livraison continue. Deux outils se distinguent souvent : Flyway et Liquibase. Les deux permettent de versionner les schémas, d’exécuter les changements de manière déterministe et d’assurer une exécution contrôlée.
Choisir entre Flyway et Liquibase
Les deux solutions résolvent un problème commun : appliquer des changements de schéma de façon fiable. Le choix dépend principalement du mode de définition des changements, du niveau de contrôle et des exigences d’intégration.
Flyway : scripts versionnés
Flyway s’appuie sur des scripts (souvent SQL) organisés par numéro de version. La logique est simple : un script V1 s’exécute avant V2, et ainsi de suite. Cette approche favorise la clarté et la performance d’exécution.
Liquibase : changelogs déclaratifs
Liquibase utilise des changelogs (XML/YAML/JSON ou Java DSL) décrivant des opérations atomiques. Le modèle “declaration-driven” améliore la portabilité et la réutilisation de changements.
Stratégies d’automatisation dans Spring Boot
Principe : exécuter les migrations au démarrage
Les deux outils peuvent être configurés pour lancer les migrations automatiquement lors du démarrage de l’application. L’exécution doit être sécurisée pour éviter la concurrence (plusieurs instances démarrant en parallèle).
Activer la migration de manière maîtrisée
L’automatisation “par défaut” est utile en CI/CD, mais la production peut nécessiter une orchestration plus stricte. Il est fréquent d’adopter une politique : exécuter les migrations dans un job dédié, ou limiter l’exécution concurrente via un verrouillage.
Bonnes pratiques de versionnement
Les changements doivent être strictement versionnés. La règle essentielle consiste à : ne jamais modifier l’historique d’un script déjà appliqué. Tout ajustement doit créer une nouvelle version, même si le changement concerne un point mineur.
Exemple Flyway dans Spring Boot
1) Dépendance Maven (exemple)
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>10.0.0</version>
</dependency>
2) Fichiers à placer
Les scripts sont généralement placés sous src/main/resources/db/migration. Exemple :
src/main/resources/db/migration/
V1__init.sql
V2__add_orders_table.sql
3) Configuration applicative
spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migration
spring.flyway.baseline-on-migrate=true
Le paramètre baseline-on-migrate est utile lorsqu’une base existante doit être “prise en charge” sans rejouer le passé. Il faut cependant documenter précisément la stratégie de baseline.
Exemple Liquibase dans Spring Boot
1) Dépendance Maven (exemple)
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.30.0</version>
</dependency>
2) Changelog
Un fichier typique est db.changelog-master.xml :
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.0.xsd">
<changeSet id="1" author="team">
<createTable tableName="orders">
<column name="id" type="BIGINT">
<constraints primaryKey="true" nullable="false"/>
</column>
</createTable>
</changeSet>
</databaseChangeLog>
3) Configuration applicative
spring.liquibase.enabled=true
spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.xml
Pièges fréquents (et comment les éviter)
Modifier un script ou un changelog déjà exécuté
C’est l’un des pièges les plus coûteux. Une modification “a posteriori” rend le résultat non déterministe entre environnements. La bonne pratique consiste à créer de nouvelles migrations et, si nécessaire, corriger avec des opérations compensatoires.
Ignorer le verrouillage lors de l’exécution concurrente
Lorsque plusieurs instances de l’application démarrent en parallèle, deux processus peuvent tenter d’appliquer des migrations. Les outils disposent généralement d’un mécanisme de verrouillage côté base, mais il faut : vérifier la configuration et ajuster les politiques de déploiement.
Manquer de stratégie pour les environnements “anciens”
Les bases “legacy” (créées avant l’introduction du tooling) nécessitent un baseline. Une baseline mal choisie peut entraîner des différences entre environnements et des migrations répétées ou bloquées.
Oublier la compatibilité applicative (blue/green)
L’évolution du schéma doit être pensée avec l’évolution du code. Une approche recommandée consiste à effectuer des changements en deux étapes : d’abord rendre le schéma compatible avec l’ancienne et la nouvelle version (ex. colonnes nullable), puis retirer les éléments obsolètes après stabilisation.
Risque de downtime avec des opérations lourdes
Certains DDL peuvent provoquer des verrous longs : ajout d’index non concurrent, modification de colonnes volumineuses, rechargements complets. La stratégie dépend du SGBD : planifier, utiliser les options “concurrent”, partitionner les opérations, ou exécuter des migrations dans des fenêtres contrôlées.
Ne pas gérer les contraintes et dépendances
La création/modification de contraintes (FK, CHECK, UNIQUE) peut échouer si les données existantes ne respectent pas les règles. Les migrations doivent inclure un plan de correction des données ou une étape de validation préalable.
Bonnes pratiques recommandées
- Écrire des migrations petites et testables (une intention par migration lorsque c’est possible).
- Ajouter des tests d’intégration : exécuter les migrations dans une base jetable avant les suites de tests.
- Documenter l’intention : les migrations servent de “contrat historique” pour l’équipe.
- Garder une discipline de nommage : conventions de versions, auteurs, et description claire.
- Surveiller les temps d’exécution des migrations en CI/CD pour détecter les régressions de performance.
Intégration CI/CD : trajectoire simple et robuste
Dans une chaîne CI/CD typique, une stratégie efficace consiste à : (1) exécuter les migrations sur une base de test, (2) déclencher les suites d’intégration, (3) exécuter ensuite un déploiement contrôlé en production avec un job qui applique les migrations, idéalement avec verrouillage et journalisation.
Conclusion
Flyway et Liquibase permettent d’automatiser la gestion du schéma de manière fiable dans Spring Boot. Le succès dépend toutefois moins du choix de l’outil que de la discipline d’exécution : versionner correctement, éviter la mutation d’historique, gérer la concurrence, préparer la compatibilité applicative et traiter le risque de downtime.
Checklist rapide
Migration déterministe, changelog versionné, baseline maîtrisée, verrouillage, étapes compatibles pour blue/green, et plan de performance pour les DDL lourds.
À propos de l'auteur
Laty Gueye Samba est développeur Full Stack basé à Dakar, Sénégal. Spécialiste des écosystèmes Java / Spring Boot et Angular.
Contact : latygueyesamba@gmail.com | Dakar, Sénégal