CLI tool
seppevs/migrate-mongo avatar
seppevs/migrate-mongo

migrate-mongo: numbered migration scripts for MongoDB, with a lock and an optional checksum

A database migration tool for MongoDB in Node

1,032 stars183 forksJavaScriptMIT

At a glance

What is it?
migrate-mongo is a Node command line tool for applying database migrations to MongoDB, where each migration is a JavaScript file exporting up and down functions, applied migrations are recorded in a changelog collection, and a lock collection with a TTL index prevents two deploys from migrating at once. The current version is 14.0.7 and it needs Node 20 or newer and MongoDB 4 through 7.
Who is it for?
migrate-mongo suits a Node team whose MongoDB schema changes are currently applied by hand or by a script nobody owns, and who want the applied history recorded in the database itself so a deployment knows where it is. It is the wrong choice if you want a declarative schema tool, because this runs imperative scripts you write, and a poor fit if you need migrations to be validated before they run, since nothing checks that your down function undoes your up function.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the tool is and what it is not

migrate-mongo is described as a database migration tool for MongoDB running in Node.js, and the package description is A database migration tool for MongoDB in Node. The model is the familiar one. You write migration files, each of which is a script with an up and a down function, the tool numbers them by timestamp, applies the pending ones in order, and records what it applied in a collection inside the database. The requirements are Node.js 20.0.0 or newer and MongoDB 4.x, 5.x, 6.x or 7.x. What it is not is a schema definition tool: there is no desired-state file that gets diffed, and the migrations are ordinary JavaScript that you write by hand, which means the diffing and the planning are your job.

The command set is small, and each command has one job

The CLI usage is a short list. init initializes a new migration project. create with a description creates a new database migration. up runs all pending database migrations. down undoes the last applied database migration. status prints the changelog of the database, and help displays help for a command. There is also a version flag. The design point is that up and down are the only two that change data, and down is deliberately singular, undoing one migration at a time rather than rolling back to a named point, which is a choice that keeps the rollback surface small and makes the operation predictable. The installation is a global npm install of migrate-mongo, and the package is marked preferGlobal because the tool is meant to be invoked from a shell rather than imported.

bash
$ npm install -g migrate-mongo

Initialising a project, and the config file that holds the database URL

You make a directory for the migrations and change into it, then run migrate-mongo init, which reports that initialization was successful and asks you to edit the generated migrate-mongo-config.js file. By default this creates a CommonJS project, and the init command takes an -m esm flag if you would rather use ES modules, which matters because the config file's moduleSystem setting and the migration file format both have to agree. The init does two things, it creates a sample config file and it creates a migrations directory. The config file returns an object or a promise, and the part you must change is the mongodb url, which defaults to mongodb://localhost:27017, along with the databaseName, and you can alternatively encode the database name in the URL and leave the databaseName property out. The other settings are marked as only to edit when really necessary.

bash
$ mkdir albums-migrations
$ cd albums-migrations
$ migrate-mongo init
Initialization successful. Please edit the generated migrate-mongo-config.js file

The migration file: an up and a down, with a signature that has to match

Creating a migration with a description generates a timestamped file in the migrations directory, for example migrations/20160608155948-blacklist_the_beatles.js, containing an object with an up and a down function. The template documents the parameters, the db object which is the official MongoDB db object, and the client object which is a MongoClient instance that you can omit if you do not need it. There are two ways to implement the functions. You can return a Promise, or you can use async and await, which the documentation recommends and which is especially useful when a migration performs multiple operations against the database. The rule is that the signature has to match, so a plain function up(db, client) should return a Promise, and an async function up(db, client) should contain await keywords and return a Promise. The documentation also says not to forget the down part, and the down function is where the accuracy of the tool depends on your own care.

javascript
module.exports = {
  async up(db) {
    await db.collection('albums').updateOne({artist: 'The Beatles'}, {$set: {blacklisted: true}});
    await db.collection('albums').updateOne({artist: 'The Doors'}, {$set: {stars: 5}});
  },

  async down(db) {
    await db.collection('albums').updateOne({artist: 'The Doors'}, {$set: {stars: 0}})
  }
};

The lock, the changelog, and the TTL value that decides whether you are protected

Three configuration keys in the generated file determine how the tool behaves against concurrent deployments, and the lock is the one worth thinking hardest about. The changelogCollectionName is the collection where the applied changes are stored, and the lockCollectionName is the collection where the lock will be created. The lockTtl value is the value in seconds for the TTL index used for the lock, and a value of 0 will disable the feature. That is the trap. With the default of 0 there is no lock at all, so two deploys can apply migrations concurrently. With a TTL set, the lock expires on its own after that many seconds, which is what stops a crashed migration from blocking the pipeline forever, but the same mechanism means a migration that legitimately runs longer than the TTL can be overtaken. The choice is a trade between a stuck lock and a concurrent run, and the documentation does not tell you which way to lean, so you have to know how long your migrations take.

The file hash option, and the requirement it places on your scripts

The useFileHash option enables the algorithm to create a checksum of the file contents and uses that in the comparison to determine if the file should be run, and the config file carries a warning that it requires that scripts are coded to be run multiple times. That requirement is the whole trade. With hashing on, the tool compares the contents of a migration file against the hash recorded when it was applied, so if you edit a migration that has already run, the tool detects the difference and re-runs it, which is the behaviour you want when a migration was wrong. But re-running it means running it twice, so every statement in it has to be idempotent. An updateOne that sets a field is fine, an insert that creates a document is not, because the second run creates a duplicate. Turning the option on without auditing your migrations for idempotency is the way to get a corrupted dataset.

The package shape, and the peer dependency that decides compatibility

The package manifest is small and the choices are deliberate. The runtime dependencies are just cli-table3 for the status output and commander for the argument parsing, and the MongoDB driver is a peer dependency rather than a direct one, spanning ^4.4.1, ^5.0.0, ^6.0.0 and ^7.0.0, so the tool works with whichever driver version your application already has and you are not forced into a second copy. The package is type module, with the main entry at lib/migrate-mongo.js and an exports map that offers an import path and a require path pointing at a .cjs build, so a CommonJS application can still consume the library. The bin entry is bin/migrate-mongo.js. The tests are Vitest with coverage, the linting is ESLint over lib/ and test/, and the dev dependencies include mongodb-memory-server, which is how the test suite gets a real MongoDB without one being installed. There is a samples/ directory with commonjs/ and esm/ variants.

Upkeep, licence and what to check before you adopt it

The version in the package manifest is 14.0.7, the author is Sebastian Van Sande, and the licence is MIT with the LICENSE file at the repository root. The last push to the repository was on 2026-04-15, the repository is not archived, and there are no GitHub releases, so the changelog in the repository is the release record and the npm tag is the artefact. The repository layout is conventional for a Node CLI, with bin/ for the executable, lib/ for the implementation, test/ for the suite, samples/ for the two module systems, a vitest.config.js and an eslint.config.js. Two things are worth checking before you adopt it. The first is the lock TTL, because the default disables the feature and that decision is yours. The second is the down function, because the tool will happily apply a migration whose rollback is wrong, and the status output will show a clean history while your data is in a state the down path cannot describe.

Editorial conclusion

migrate-mongo suits a Node team whose MongoDB schema changes are currently applied by hand or by a script nobody owns, and who want the applied history recorded in the database itself so a deployment knows where it is. It is the wrong choice if you want a declarative schema tool, because this runs imperative scripts you write, and a poor fit if you need migrations to be validated before they run, since nothing checks that your down function undoes your up function. Before adopting it, decide how you will set the lock TTL, because the default of 0 disables the feature and a stale lock with no expiry will block a deploy indefinitely, and note that the file hash option only works if your migrations are written to be safe to run twice.

Frequently asked questions

What is migrate-mongo?

It is a database migration tool for MongoDB running in Node.js, published to npm as migrate-mongo. It requires Node.js 20.0.0 or newer and MongoDB 4.x, 5.x, 6.x or 7.x, and the licence is MIT.

How do I create a migration with migrate-mongo?

Run migrate-mongo create with a description from the directory holding your migrations folder, which generates a timestamped file such as migrations/20160608155948-blacklist_the_beatles.js. The file exports an up and a down function, and the documentation says not to forget the down part as well.

How does migrate-mongo prevent two deployments from migrating at once?

It creates a lock in the collection named by lockCollectionName, and the lockTtl value sets the seconds for the TTL index used for the lock, where a value of 0 disables the feature. A TTL lets a stale lock expire, but it also means a migration running longer than the TTL can be overtaken.

What does the useFileHash option do in migrate-mongo?

It enables an algorithm to create a checksum of the file contents and uses that in the comparison to determine if the file should be run, so an edited migration that has already been applied is detected. The config file notes that it requires scripts to be coded to be run multiple times, so every statement must be idempotent.

How do I set up a new migrate-mongo project?

Create a directory for the migrations and change into it, then run migrate-mongo init, which creates a sample migrate-mongo-config.js and a migrations directory. The init command takes an -m esm flag for ES modules instead of the default CommonJS, and you then edit the config to set the mongodb url and the database name.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. seppevs/migrate-mongo on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/seppevs-migrate-mongo.svg)](https://hysenlabs.com/projects/seppevs-migrate-mongo)

Was this useful?