Skip to main content
Global
AIMenta
Blog

APAC Database Schema Migration Guide 2026: Flyway, Liquibase, and Atlas for DevOps-Native Database Change Management

A practitioner guide for APAC DevOps and platform engineering teams selecting database schema migration tooling in 2026 — covering Flyway for SQL-first numbered migration files in CI/CD pipelines, Liquibase for XML/YAML changeset compliance workflows with automatic rollback generation, and Atlas for declarative schema-as-code with automated SQL generation and drift detection across APAC PostgreSQL, MySQL, Oracle, and TiDB environments.

AE By AIMenta Editorial Team ·

The APAC Database Migration Problem

APAC engineering teams that have adopted CI/CD for application code often maintain a manual exception for database schema changes: the DBA applies schema changes manually before deployment, or migrations run outside the pipeline as a separate operation. The result is deployment coupling — APAC application code and its required schema changes deploy out of sync — and audit gaps where the APAC schema change history exists only in tribal memory.

Three tools address different APAC database migration workflows:

SQL-first, explicit control: Flyway applies numbered SQL migration files sequentially — APAC teams write the exact SQL, Flyway tracks which have been applied. No abstraction between the APAC engineer and the SQL.

Changeset abstraction with compliance audit: Liquibase manages changes through typed changesets (XML, YAML, JSON) with automatic rollback generation and structured audit trails. Appropriate for APAC regulated environments where schema change governance is required.

Declarative schema-as-code: Atlas manages the desired schema state in HCL or SQL definitions, computes diffs against the current APAC database, and generates migration SQL automatically. Follows Terraform-style workflows for APAC platform teams treating databases as infrastructure.


Flyway: Pipeline-Native SQL Migrations for APAC Engineering Teams

The Flyway model: numbered SQL files, sequential execution

apac-service/
├── src/
│   └── ...
└── db/
    └── migration/
        ├── V1__create_apac_schema.sql
        ├── V2__add_apac_customer_table.sql
        ├── V3__create_apac_order_indexes.sql
        ├── V4__add_apac_region_column.sql
        └── V5__create_apac_notification_table.sql

Flyway reads these files in version order, compares against the flyway_schema_history table in the APAC target database, and applies any pending migrations — leaving already-applied migrations untouched.

-- V4__add_apac_region_column.sql
-- Safe APAC migration pattern: add nullable column, backfill, add constraint
ALTER TABLE apac_customer_accounts
  ADD COLUMN region_code CHAR(2);

UPDATE apac_customer_accounts
SET region_code = CASE
    WHEN country_code IN ('SG', 'MY', 'ID', 'PH', 'VN', 'TH') THEN 'SEA'
    WHEN country_code IN ('JP', 'KR', 'TW', 'CN', 'HK') THEN 'NEA'
    ELSE 'OTHER'
  END;

ALTER TABLE apac_customer_accounts
  ALTER COLUMN region_code SET NOT NULL;

CREATE INDEX idx_apac_customer_region
  ON apac_customer_accounts(region_code, country_code);

Flyway in GitHub Actions for APAC CI/CD

# .github/workflows/apac-deploy.yml
name: APAC Service Deploy

on:
  push:
    branches: [main]

jobs:
  migrate-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run APAC database migrations (Flyway)
        uses: joshuaavalon/flyway-action@v3
        with:
          url: jdbc:postgresql://${{ secrets.APAC_DB_HOST }}:5432/apac_db
          user: ${{ secrets.APAC_DB_USER }}
          password: ${{ secrets.APAC_DB_PASSWORD }}
          locations: filesystem:db/migration
          # Fail deploy if APAC schema history checksum mismatch
          validateOnMigrate: true

      - name: Deploy APAC application container
        # Application deploys only after successful APAC migration
        run: |
          kubectl set image deployment/apac-service \
            apac-service=${{ env.IMAGE }}:${{ github.sha }} \
            -n apac-production

Flyway Docker for APAC containerized pipelines

# Run APAC Flyway migration from Docker (no local Java required)
docker run --rm \
  -v "$(pwd)/db/migration:/flyway/sql" \
  flyway/flyway:latest \
  -url="jdbc:postgresql://apac-db.internal:5432/apac_db" \
  -user="apac_migrator" \
  -password="${APAC_DB_PASSWORD}" \
  -schemas="apac_core,apac_analytics" \
  migrate

# Validate APAC schema history without applying migrations
docker run --rm \
  -v "$(pwd)/db/migration:/flyway/sql" \
  flyway/flyway:latest \
  -url="jdbc:postgresql://apac-db.internal:5432/apac_db" \
  -user="apac_migrator" \
  -password="${APAC_DB_PASSWORD}" \
  validate

# Info: show APAC migration status (pending vs applied)
docker run --rm \
  -v "$(pwd)/db/migration:/flyway/sql" \
  flyway/flyway:latest \
  -url="jdbc:postgresql://apac-db.internal:5432/apac_db" \
  -user="apac_migrator" \
  -password="${APAC_DB_PASSWORD}" \
  info

Flyway configuration for APAC multi-environment deployments

# flyway.conf: APAC environment-specific configuration
# (Override with environment variables: FLYWAY_URL, FLYWAY_USER, etc.)
flyway.url=jdbc:postgresql://apac-db-prod.internal:5432/apac_db
flyway.user=apac_migrator
flyway.schemas=apac_core,apac_analytics
flyway.locations=filesystem:db/migration
flyway.validateOnMigrate=true
flyway.outOfOrder=false          # Block APAC out-of-order migrations
flyway.placeholders.apac_env=production

Liquibase: Compliance-Grade Change Management for APAC Enterprise

When APAC teams need changeset audit trails

APAC regulated industries have DBA change management processes that require:

  • Every APAC schema change tracked with author, description, and timestamp
  • Change rollback plans documented before APAC production deployment
  • Change approval workflows integrated with APAC ITSM systems

Liquibase's changelog format provides these natively.

Liquibase YAML changesets for APAC

# db/changelog/apac-changes.yaml
databaseChangeLog:
  - changeSet:
      id: "2026-04-28-001"
      author: "apac-platform-team"
      comment: "APAC: Add KYC verification status to customer accounts"
      changes:
        - addColumn:
            tableName: apac_customer_accounts
            columns:
              - column:
                  name: kyc_status
                  type: VARCHAR(20)
                  defaultValue: "pending"
                  constraints:
                    nullable: false
              - column:
                  name: kyc_verified_at
                  type: TIMESTAMP
              - column:
                  name: kyc_provider
                  type: VARCHAR(50)
      rollback:
        - dropColumn:
            tableName: apac_customer_accounts
            columnName: kyc_status
        - dropColumn:
            tableName: apac_customer_accounts
            columnName: kyc_verified_at
        - dropColumn:
            tableName: apac_customer_accounts
            columnName: kyc_provider

  - changeSet:
      id: "2026-04-28-002"
      author: "apac-data-team"
      comment: "APAC: Index for KYC status filtering queries"
      changes:
        - createIndex:
            indexName: idx_apac_customer_kyc_status
            tableName: apac_customer_accounts
            columns:
              - column:
                  name: kyc_status
              - column:
                  name: kyc_verified_at
      rollback:
        - dropIndex:
            indexName: idx_apac_customer_kyc_status
            tableName: apac_customer_accounts

Liquibase diff for APAC schema drift detection

# Compare APAC production database against APAC staging reference schema
liquibase \
  --url="jdbc:postgresql://apac-prod.internal:5432/apac_db" \
  --referenceUrl="jdbc:postgresql://apac-staging.internal:5432/apac_db" \
  --username=apac_migrator \
  --password="${APAC_DB_PASSWORD}" \
  diff

# Generate APAC changelog from diff (APAC staging → APAC production)
liquibase \
  --url="jdbc:postgresql://apac-prod.internal:5432/apac_db" \
  --referenceUrl="jdbc:postgresql://apac-staging.internal:5432/apac_db" \
  --username=apac_migrator \
  --password="${APAC_DB_PASSWORD}" \
  --changelogFile=apac-prod-missing-changes.yaml \
  diffChangeLog

Atlas: Declarative Schema-as-Code for APAC Platform Teams

The Atlas model: declare state, generate diff

# schema.hcl: Desired APAC PostgreSQL schema state
schema "apac_core" {}

table "apac_customer_accounts" {
  schema = schema.apac_core

  column "account_id" {
    type = uuid
    default = sql("gen_random_uuid()")
  }

  column "customer_id" {
    type = uuid
    null = false
  }

  column "country_code" {
    type    = char(2)
    null    = false
    comment = "APAC ISO 3166-1 alpha-2 country code"
  }

  column "account_balance" {
    type    = decimal(18, 4)
    null    = false
    default = 0
  }

  column "currency_code" {
    type    = char(3)
    null    = false
    comment = "APAC ISO 4217 currency code"
  }

  column "created_at" {
    type    = timestamptz
    default = sql("NOW()")
  }

  primary_key {
    columns = [column.account_id]
  }

  index "idx_apac_customer_id" {
    columns = [column.customer_id]
  }

  index "idx_apac_country_balance" {
    columns = [column.country_code, column.account_balance]
  }
}
# Atlas: inspect current APAC database schema
atlas schema inspect \
  --url "postgres://apac_migrator:${APAC_DB_PASSWORD}@apac-db.internal:5432/apac_db" \
  --schema apac_core \
  > current_schema.hcl

# Atlas: compute diff between desired and current APAC state
atlas schema diff \
  --from "postgres://apac_migrator:${APAC_DB_PASSWORD}@apac-db.internal:5432/apac_db?search_path=apac_core" \
  --to "file://schema.hcl"

# Atlas: apply APAC schema to match desired state (with dry-run first)
atlas schema apply \
  --url "postgres://apac_migrator:${APAC_DB_PASSWORD}@apac-db.internal:5432/apac_db?search_path=apac_core" \
  --to "file://schema.hcl" \
  --dry-run    # Remove for actual APAC application

Atlas versioned migrations for APAC CI/CD

# Atlas generates versioned migrations from schema diff
atlas migrate diff add_kyc_columns \
  --dir "file://db/migrations" \
  --to "file://schema.hcl" \
  --dev-url "docker://postgres/15/apac_dev"

# Generated migration file (Atlas writes the SQL)
cat db/migrations/20260428121500_add_kyc_columns.sql
# -- atlas:name add_kyc_columns
# ALTER TABLE "apac_core"."apac_customer_accounts"
#   ADD COLUMN "kyc_status" VARCHAR(20) NOT NULL DEFAULT 'pending',
#   ADD COLUMN "kyc_verified_at" TIMESTAMPTZ,
#   ADD COLUMN "kyc_provider" VARCHAR(50);

Atlas GitHub Actions for APAC PR schema review

# .github/workflows/apac-schema-review.yml
name: APAC Schema Migration Lint

on:
  pull_request:
    paths:
      - 'db/migrations/**'
      - 'schema.hcl'

jobs:
  atlas-lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Atlas lint APAC migrations
        uses: ariga/atlas-action/migrate/lint@v1
        with:
          dir: db/migrations
          dir-format: atlas
          dev-url: "docker://postgres/15/apac_dev"
          # Blocks APAC PRs containing:
          # - DROP TABLE / DROP COLUMN without prior data migration
          # - NOT NULL column additions without DEFAULT
          # - Index removals that break APAC query plans

APAC Database Migration Tool Selection

APAC Team Profile                    → Tool        → Reason

SQL-fluent engineers, explicit       → Flyway      Write exact APAC SQL; no abstraction;
control, CI/CD native                →             fastest to adopt; Docker-native

Enterprise APAC DBA team,           → Liquibase   Changeset audit trail; auto rollback
Oracle/SQL Server, compliance audit  →             generation; multi-DB dialect support

Platform engineering, Terraform      → Atlas       Declarative schema-as-code; drift
workflows, PostgreSQL/MySQL          →             detection; automated APAC SQL generation

APAC brownfield Oracle database,     → Liquibase   Liquibase diff + diffChangeLog
unknown schema state                 →             reconstructs APAC changeset history

APAC greenfield service,             → Atlas       Start from desired state; Atlas
PostgreSQL, IaC-first culture        →             generates all APAC migration SQL

APAC Laravel/Django/Rails app        → Framework   Use built-in ORM migrations for
(ORM-managed schema)                 migrations    APAC application-owned schema;
                                                   reserve Flyway/Liquibase/Atlas
                                                   for APAC shared/platform databases

Related APAC Data Infrastructure Resources

For the distributed databases that APAC migration tooling manages at scale, see the APAC distributed database guide covering TiDB, CockroachDB, and Valkey.

For the supply chain security scanning that runs alongside APAC database migration CI/CD gates, see the APAC supply chain security guide covering Checkov, Gitleaks, and TruffleHog.

For the CI/CD platform engineering tools that host APAC migration pipelines, see the APAC CI/CD platform engineering guide covering Tekton, Buildkite, and Gradle.

Beyond this insight

Cross-reference our practice depth.

If this article matches your stage of thinking, the underlying capabilities ship across all six pillars, ten verticals, and nine Asian markets.

Keep reading

Related reading

Want this applied to your firm?

We use these frameworks daily in client engagements. Let's see what they look like for your stage and market.