Mongock: ChangeUnits

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.

@ChangeUnit

Every Mongock migration is a class annotated @ChangeUnit, with four attributes:

Attribute Meaning

id

Unique identifier — Mongock’s equivalent of a Liquibase changeset’s id (Core Concepts).

order

A string used to sort change units before execution — typically zero-padded ("001", "002") so lexicographic and numeric ordering agree.

author

Who wrote it, for the audit trail — purely informational, not part of identity the way Liquibase’s author is.

systemVersion

Optional — a version marker checked against the runner’s configured startSystemVersion/endSystemVersion window (startSystemVersion ⇐ systemVersion < endSystemVersion), not an exact-match check. Lets a change unit’s activation be tied to a release window rather than requiring the running system to be on one specific version.

@Execution — Mandatory

Every @ChangeUnit needs exactly one @Execution method: the code that actually performs the migration. It can accept any of Mongock’s supported dependency types as parameters (a MongoDatabase, a Spring Data MongoTemplate, or an application-defined @Inject-able bean), depending on the driver in use (Mongock: Getting Started):

@Execution
public void execution(MongoDatabase db) {
    db.getCollection("person").updateMany(
        Filters.exists("status", false),
        Updates.set("status", "ACTIVE"));
}

The inverse of @Execution, run if this migration needs to be undone. Unlike Liquibase, Mongock never generates this automatically — it is always hand-written code, and the official reference marks it as highly recommended rather than mandatory precisely because a change unit is materially riskier without one:

@RollbackExecution
public void rollback(MongoDatabase db) {
    db.getCollection("person").updateMany(
        Filters.eq("status", "ACTIVE"),
        Updates.unset("status"));
}

A change unit with no @RollbackExecution can still run forward normally, but there is then no supported way to undo it if it turns out to be wrong — see Core Concepts' note on forward-only vs. reversible changes.

@BeforeExecution — Optional

An optional hook that runs before @Execution, outside of whatever transaction Mongock would otherwise wrap the execution in (Mongock: Transactions & Locking). It exists for operations MongoDB does not allow inside a multi-document transaction — most commonly DDL-like operations such as creating a collection or an index, which MongoDB requires to run outside any active transaction:

@BeforeExecution
public void beforeExecution(MongoDatabase db) {
    db.createCollection("audit_log");
}

@Execution
public void execution(MongoDatabase db) {
    db.getCollection("audit_log").insertOne(new Document("event", "initialized"));
}

A matching @RollbackBeforeExecution is available to undo whatever @BeforeExecution did, mirroring @RollbackExecution for the main method.

Code-First vs. Declarative: The Contrast With Liquibase

The defining difference from Liquibase is that a Mongock change unit is Java code, compiled and reviewed like any other class, rather than a declarative file in a separate format. This means:

  • Full language power — loops, conditionals, calling into application services — is available inside a migration, where a declarative changelog would need Liquibase’s more limited built-in change types or an embedded script.

  • There is no DBA-reviewable, non-Java artifact — reviewing a Mongock migration means reading Java.

  • Ordering and the classpath-scanned "changelog" model follow the same rule as every code-based tool in this guide (Core Concepts' Changelog / Ordering section).

@BeforeExecution, @Execution and @RollbackExecution (with @RollbackBeforeExecution) can all live on the same class — see the individual snippets above; there’s no requirement to split them across separate classes.

See the Migration / ChangeUnit reference for the full annotation and dependency-injection reference.