Evolving the Database Model

This section documents schema/database evolution using version-controlled migration tools — Liquibase (relational/SQL), Mongock (MongoDB, Java-native) and Flamingock (Mongock’s successor, generalized to any external system) — as described by each tool’s own official documentation: liquibase.org and docs.liquibase.com for Liquibase, docs.mongock.io for Mongock, and docs.flamingock.io for Flamingock — which are the references these pages are written and verified against.

This content was generated with the assistance of AI and should be verified against those official docs before being relied on in production.

Mongock is now maintained under the Flamingock GitHub organization (github.com/flamingock/mongock), and Flamingock is positioned as its successor — see Coming from Mongock. Readers starting a new project should default to Flamingock unless they have a specific reason to stay on Mongock.

This section’s bibliography lists the reference material consulted while preparing these pages.

A database schema is never finished. Tables gain columns, MongoDB collections gain new document shapes, indexes get added and dropped, and every one of those changes has to land the same way in a developer’s laptop, a CI pipeline, staging and production — in the right order, exactly once, with a record of what ran and when. Making that change by hand — a DBA running a script, a developer clicking through a GUI — works for a while and then fails in the way manual processes always fail: one environment drifts from another, nobody remembers which scripts already ran where, and there is no way to undo a bad change short of restoring a backup.

Migrations as code solves this by treating every schema/model change as a versioned, ordered unit of work, committed to the same repository as the application code that depends on it. Each unit runs at most once per target, in a fixed order, and its execution is durably recorded — so any environment can be brought from "empty" to "current" (or from any past state to current) by replaying the same units, and the record of what ran becomes an audit trail for free. This gets you:

  • Repeatability — the same units, applied in the same order, produce the same schema everywhere.

  • Auditability — a durable record of what changed, when, and (via version control) who changed it and why.

  • Team coordination — schema changes go through the same review and merge process as any other code change, instead of living as tribal knowledge or a shared script folder.

  • Environment parity — development, CI, staging and production converge on the same state instead of drifting apart silently.

This guide covers three tools that implement this idea, each aimed at a different slice of the problem: Liquibase for relational/SQL databases with a declarative changelog, Mongock for MongoDB from Java/Spring using code-first change units, and Flamingock — Mongock’s successor — which generalizes the same Change-as-Code model to any target system, not just a database. Core Concepts introduces the vocabulary all three share before any tool-specific page uses it, and Choosing a Migration Tool helps you land on one.

At a Glance

Tool Target system(s) Changelog format Tracking mechanism Best fit

Liquibase

Relational/SQL databases (any JDBC target)

Declarative SQL, XML, YAML or JSON changelog files

DATABASECHANGELOG / DATABASECHANGELOGLOCK tables in the target database

Relational schemas, polyglot stacks with no JVM requirement, DBA-reviewable changelogs

Mongock

MongoDB only

Code-first Java @ChangeUnit classes

An audit collection in the target MongoDB deployment, plus a distributed lock collection

Existing MongoDB + Java/Spring projects already invested in code-first change units

Flamingock

Any target system — SQL, MongoDB, DynamoDB, Couchbase, message brokers, APIs, cloud services

Code-first Java @Change classes, grouped into stages and pipelines

A configurable audit store, decoupled from any single target system

New projects, multi-target systems, or migrating an existing Mongock codebase forward

What’s Covered

Core Concepts

  • Core Concepts — the vocabulary every tool shares: change unit, changelog/ordering, idempotency, checksums, the audit/tracking table, distributed locking, contexts and environments, forward-only vs. reversible changes, and dry runs.

Choosing a Migration Tool

Liquibase

  • Liquibase: Getting Started — installing the CLI, running via the Maven/Gradle plugin or Spring Boot auto-run, the four changelog formats, and a first minimal changeset applied with liquibase update.

  • Liquibase: Changelogs & Changesets — changeset identity (id/author/filename), the one-change-type-per-changeset recommendation, include/includeAll, and generating a changelog from an existing database or a schema diff.

  • Liquibase: Preconditions, Contexts & Labels — gating a changeset on database state, tagging changesets per environment, and the author-vs-operator split between contexts and labels.

  • Liquibase: Rollback — automatic inverse SQL, custom <rollback> blocks, and rolling back by tag, count or date.

  • Liquibase: Tracking & Locking — the DATABASECHANGELOG/DATABASECHANGELOGLOCK tables, checksum mismatches, and releasing a stuck lock.

Mongock

  • Mongock: Getting Started — the available drivers (MongoDB Sync, Spring Data, Reactive) and runners (Standalone vs. Spring Boot), and a first @ChangeUnit.

  • Mongock: ChangeUnits — @ChangeUnit, the mandatory @Execution method, @RollbackExecution, the @BeforeExecution hook, and code-first migrations as the contrast with Liquibase’s declarative changelogs.

  • Mongock: Transactions & Locking — transactional execution on a replica set/sharded cluster, the distributed lock, and multi-tenant migrations.

Flamingock

Best Practices

  • Best Practices — expand/contract, one logical change per change unit, never editing an already-applied change, testing migrations in CI, coordinating rollout with the application deploy, and zero-downtime strategies.