Make money doing the work you believe in

๐‡๐จ๐ฐ ๐๐จ ๐ฒ๐จ๐ฎ ๐ฆ๐ข๐ ๐ซ๐š๐ญ๐ž ๐ฌ๐œ๐ก๐ž๐ฆ๐š ๐œ๐ก๐š๐ง๐ ๐ž๐ฌ ๐ฌ๐š๐Ÿ๐ž๐ฅ๐ฒ ๐ข๐ง ๐’๐ฉ๐ซ๐ข๐ง๐  ๐๐จ๐จ๐ญ ๐ฐ๐ข๐ญ๐ก ๐๐จ๐ฌ๐ญ๐ ๐ซ๐ž๐’๐๐‹? ๐ฐ๐ข๐ญ๐ก ๐‘๐ž๐š๐ฅ-๐“๐ข๐ฆ๐ž ๐„๐ฑ๐š๐ฆ๐ฉ๐ฅ๐ž

=================================

In Spring Boot projects, I handle schema migrations using a versioned migration tool like Flyway or Liquibase, rather than relying on Hibernate auto-DDL. This gives us controlled, repeatable, and auditable database changes across environments

Each schema change is written as a migration script and versioned โ€” for example, adding a column, creating an index, or modifying a constraint. These migrations are applied automatically at application startup or during deployment, and the tool tracks which migrations have already run

To keep migrations safe, I follow a few best practices. First, migrations are backward-compatible whenever possible โ€” for example, adding new nullable columns before removing old ones. Destructive changes like dropping columns are done in later releases after the application code no longer depends on them

Second, all migrations are tested in lower environments using production-like data. We also make sure migrations are idempotent and transactional, which PostgreSQL supports well, so failures can be rolled back safely.

Finally, migrations are part of the CI/CD pipeline, and production changes are always backed up. This way, schema evolution is predictable, reversible when needed, and aligned with application releases

๐‘๐ž๐š๐ฅ-๐“๐ข๐ฆ๐ž ๐”๐ฌ๐ž ๐‚๐š๐ฌ๐ž: ๐’๐š๐Ÿ๐ž๐ฅ๐ฒ ๐€๐๐๐ข๐ง๐  ๐š ๐๐จ๐ง-๐๐ฎ๐ฅ๐ฅ๐š๐›๐ฅ๐ž ๐‚๐จ๐ฅ๐ฎ๐ฆ๐ง

---------------------------------------

๐’๐œ๐ž๐ง๐š๐ซ๐ข๐จ :

We had a users table in PostgreSQL, and the business requirement was to add a status field to track whether a user is ACTIVE, SUSPENDED, or DELETED. The application is already live with millions of records

๐๐ซ๐จ๐›๐ฅ๐ž๐ฆ

We canโ€™t directly add a NOT NULL column, because existing rows donโ€™t have values and it would either fail or cause downtime

๐’๐ญ๐ž๐ฉ 1: ๐€๐๐ ๐ญ๐ก๐ž ๐œ๐จ๐ฅ๐ฎ๐ฆ๐ง ๐š๐ฌ ๐ง๐ฎ๐ฅ๐ฅ๐š๐›๐ฅ๐ž

ALTER TABLE users ADD COLUMN status VARCHAR(20);

This change is backward-compatible and doesnโ€™t break the running application

๐’๐ญ๐ž๐ฉ 2: ๐๐š๐œ๐ค๐Ÿ๐ข๐ฅ๐ฅ ๐ž๐ฑ๐ข๐ฌ๐ญ๐ข๐ง๐  ๐๐š๐ญ๐š

UPDATE users SET status = 'ACTIVE' WHERE status IS NULL;

This can be done in batches to avoid long-running locks

๐’๐ญ๐ž๐ฉ 3: ๐”๐ฉ๐๐š๐ญ๐ž ๐š๐ฉ๐ฉ๐ฅ๐ข๐œ๐š๐ญ๐ข๐จ๐ง ๐œ๐จ๐๐ž

We update the Spring Boot code to always write status for new users

๐’๐ญ๐ž๐ฉ 4: ๐€๐๐ ๐๐Ž๐“ ๐๐”๐‹๐‹ ๐œ๐จ๐ง๐ฌ๐ญ๐ซ๐š๐ข๐ง๐ญ ๐ข๐ง ๐š ๐ฅ๐š๐ญ๐ž๐ซ ๐ฆ๐ข๐ ๐ซ๐š๐ญ๐ข๐จ๐ง

ALTER TABLE users ALTER COLUMN status SET NOT NULL;

At this point, the database constraint enforces data integrity safely.โ€

All these steps are implemented as separate Flyway or Liquibase migrations, versioned and applied through CI/CD. Each release moves the schema forward without breaking running code

Jan 7
at
9:15 AM
Relevant people

Log in or sign up

Join the most interesting and insightful discussions.