How can I best handle database migrations in a Java Spring Boot multi-instance application deployed as a microservice in Kubernetes (for future in Cloud Native Env), considering the following constraints and options?
Context:
- It used Flyway for SQL migrations, with plans to add Java-based migrations.
- It needs to run in multiple instances (replicas).
- Currently, all DB migrations are done automatically during application context initialization, which can take a long time (from over 5 minutes to a few hours, e.g. alter or complex update of table with millions of record).
- Liveness, Readiness and Startup probes are added for the Kubernetes container, making it impractical to keep DB migrations within the application startup/initialization scope.
Some Options Considered:
- Use the same application (Spring Boot fat jar) but trigger migrations only through an input argument or class path invocation of an alternative main method, then immediately invoke a shutdown hook.(This was my first choice, but some colleagues objected that application should have single responsibility, so that proposed one of the below:…)
- Use the
flyway/flyway
Docker image to run DB migrations, with SQLs mounted as config-maps – often met examples on various forums, but I don’t want put big, complex SQL in ConfigMap (security reasons, size limitations, etc), also I’ll have Java Migrations. - Build a separate image
FROM flyway/flyway
with SQL migrations and Java migrations (as JARs) included in it (COPY
), along with necessary configurations.
Some Additional Sub-Questions:
- What are the pros and cons of these approaches?
- Are there any alternative approaches that might be better?
- What are the best practices in the community for handling such scenarios?