Mongock: Transactions & Locking
|
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. |
Transactional Execution
MongoDB supports multi-document ACID transactions only on a replica set or sharded cluster — never on a
standalone mongod. When the target deployment supports it, Mongock wraps a change unit’s @Execution (and
@RollbackExecution) in a transaction automatically: if the method throws partway through, every write it made
is rolled back by MongoDB itself, rather than being left half-applied.
This is exactly why @BeforeExecution exists (Mongock:
ChangeUnits): operations MongoDB disallows inside a transaction — creating a collection or an index chief among
them — have to run outside it, which is what that hook is for. Against a standalone mongod with no
transaction support at all, Mongock executes the change unit without transactional guarantees, and idempotency
(Core Concepts) becomes the only safety net against a
partially-applied run.
The Distributed Lock
Before running any pending change units, Mongock acquires a lock document in its own lock collection in the target MongoDB deployment — the same distributed-locking concept every tool in this guide implements (Core Concepts). This is what prevents two instances of an application starting up concurrently from both attempting to run the same change units. If a process holding the lock crashes, the lock document can expire based on Mongock’s configured lock lease duration, or it can require manual clearing depending on configuration — consult Mongock Documentation for the exact lock-acquisition and lease settings for the version in use.
Multi-Tenant Considerations
A common Mongock deployment shape is one application serving many tenants, each with its own MongoDB database (or, less commonly, a shared database with tenant-scoped collections). Running the same change units against every tenant database raises two considerations:
-
Per-tenant tracking — Mongock’s audit collection needs to live per tenant (alongside that tenant’s own data), or be keyed by tenant, so that one tenant’s applied change units are tracked independently of every other tenant’s. Running the standard single-database setup once per tenant connection, iterating tenants in the application startup code, is the usual approach.
-
Partial failure across tenants — if a change unit succeeds for some tenants and fails for others (a transient error, a tenant with an unexpected existing data shape), the tenants are now in different states. The application needs its own retry/alerting strategy for this, since Mongock’s transactional guarantee (Transactional Execution) is scoped to one execution against one target, not to a fan-out across many.
For guidance on when a system’s needs outgrow Mongock’s MongoDB-only model, see Choosing a Migration Tool.