Real World Example

Adding Product Variants at ShopEase

Fashion sites like Myntra and Ajio sell one product in many sizes and colours. ShopEase adds a product_variants table, moves stock from products to variants, and keeps the API working throughout.

-- V14__create_product_variants.sql  (expand)
CREATE SEQUENCE product_variant_seq START WITH 1 INCREMENT BY 50;
CREATE TABLE product_variants (
    id         BIGINT PRIMARY KEY,
    product_id BIGINT NOT NULL REFERENCES products(id),
    size       VARCHAR(10),
    color      VARCHAR(30),
    stock      INT NOT NULL DEFAULT 0,
    version    BIGINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_variants_product ON product_variants(product_id);

-- V15__backfill_default_variants.sql  (migrate: one default variant per existing product)
INSERT INTO product_variants (id, product_id, size, color, stock, version)
SELECT nextval('product_variant_seq'), p.id, 'STD', 'DEFAULT', p.stock, 0
  FROM products p
 WHERE NOT EXISTS (SELECT 1 FROM product_variants v WHERE v.product_id = p.id);

-- V18__drop_products_stock.sql  (contract, two releases later)
ALTER TABLE products DROP COLUMN stock;

CI Check

Pipeline

The pipeline runs all migrations against a fresh PostgreSQL container and then boots Hibernate with validate (see Testing the Persistence Layer):

./mvnw -q verify

Example output

Flyway Community Edition 10.x by Redgate
Successfully validated 18 migrations
Creating Schema History table "public"."flyway_schema_history" ...
Migrating schema "public" to version "1 - create categories and products"
...
Migrating schema "public" to version "18 - drop products stock"
Successfully applied 18 migrations to schema "public", now at version v18
Tests run: 42, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

Tip: Also run the migrations against a copy of production data before release: a backfill that takes 2 seconds on test data can take 40 minutes on 30 million rows.