MongoMig
Alembic-style schema evolution and migrations for MongoDB.
Change your models, see exactly what changed, generate a migration, review its impact, and run it safely. Built for Python services (FastAPI, Flask, workers) on PyMongo or Beanie.
$ mongomig diff
USERS
+ status: string = 'active' REQUIRES_DATA_MIGRATION backfill existing documents with 'active'
+ age: int | null = None SAFE defaults to None: existing documents need no backfill
+ given_name: string MANUAL_REVIEW required, with no default: choose a value for existing documents
- first_name WARNING removed from the model; existing data is kept (not deleted)
+ index users_email_unique (email ↑, unique) WARNING fails if existing documents contain duplicates
Possible rename: users.first_name → given_name (85% similar). If so, pass --rename users.first_name:given_name
$ mongomig revision --autogenerate -m "evolve users" --rename users.first_name:given_name
Generated b91baf4fd592 → migrations/versions/20260925_1115_b91baf4fd592_evolve_users.py
$ mongomig plan
b91baf4fd592 evolve users Risk: HIGH
users rename_field $rename first_name ~4,218,901 docs · collection scan
users backfill $set status ~4,218,901 docs · collection scan
users create_index users_email_unique (unique) 4,218,901 docs
⚠ will fail: duplicate values exist, e.g. {'email': 'sam@example.com'}
$ mongomig upgrade
Why MongoMig
- Autogenerate from your models: plain Pydantic (
@collection) or Beanie documents, no extra declarations. Backfills with your defaults, renames, indexes,$jsonSchemavalidators. - Every change is classified: SAFE, WARNING, REQUIRES_DATA_MIGRATION or MANUAL_REVIEW.
Risky changes become commented
TODO(review)blocks, and data is never deleted automatically. - Deterministic diffs: models are compared with a committed schema snapshot rather than a sampled database, so results are the same on every machine and in CI.
- Knows how you store data:
model_dump()vsjsonable_encoderstores dates as different BSON types, and MongoMig warns about types PyMongo can't store. - Production-grade execution: distributed lock, batched operations with progress and
ETA, retries, checkpoints so a failed migration resumes where it stopped
(
mongomig resume), transactions, checksums, confirmation before destructive migrations, and restorable backups. - See the impact first:
plan/--dry-runestimate documents touched and collection scans, and predict unique-index failures and validator rejections against real data. - Catch drift:
mongomig driftcompares your models with the data actually stored. It reports missing fields, unexpected types (age: string in 5.7% of documents), unknown fields, and missing indexes or validators, with thresholds for CI or scheduled checks. - Keeps history manageable:
mongomig squashreplaces old revisions with one. Existing databases adopt it automatically, and new ones replay a single revision. - Built for CI:
mongomig validate,--jsonoutput everywhere, documented exit codes.
Install
pip install mongomig # add [beanie] for Beanie support
Python 3.11+, MongoDB 6.0+ (tested on 6.0, 7.0, 8.0).
Quick start
mongomig init # mongomig.yaml + migrations/
export MONGODB_URI="mongodb://localhost:27017"
# register your models in migrations/env.py (see below), then:
mongomig revision --autogenerate -m "initial" # new project
mongomig baseline # ...or an existing database
mongomig upgrade
# app/models.py
from pydantic import BaseModel
from mongomig import collection, Index
@collection("users", indexes=[Index("email", unique=True)])
class User(BaseModel):
name: str
email: str
status: str = "active"
# migrations/env.py
from mongomig import MongoMetadata
import app.models # noqa: F401
target_metadata = MongoMetadata.default(storage="python") # or "json"; Beanie: register_beanie(...)
Everyday loop: edit models → mongomig diff → mongomig revision --autogenerate -m "..." →
review and commit → CI mongomig validate → deploy mongomig plan + mongomig upgrade.
On a schedule: mongomig drift --check.
$ mongomig drift
USERS 10,000 sampled of ~4,982,133 documents
✗ (index) index users_email_unique (email ↑, unique) is not in the database
✗ age expected int | null · observed string 5.70% > 0.5%
✗ profile.verified required by the model · missing in 10.1% of documents > 0.5%
! nickname not in the model · present in 0.36% of documents ≤ 1%
Documentation
Full docs: https://anon-000.github.io/mongomig/
- Getting started
- Concepts: snapshots, storage profiles, classifications
- Writing migrations:
ctxandctx.opsreference - Autogenerate: what gets generated and how to review it
- Production guide: permissions, plan, locking, backups, recovery
- Coming from Alembic or hand-written scripts?
- CLI reference · Python API · Troubleshooting
Examples: FastAPI + Pydantic · FastAPI + Beanie
Status
The MVP is complete (config, revisions, upgrade/downgrade, schema inspection, diff, autogenerate, plan/dry-run, locking, batching, backups, CI checks), plus drift detection, resumable migrations, transactions and squashing. Next: observability (OpenTelemetry / Prometheus metrics). Ideas and feedback welcome.
Development
make install # uv venv + editable install with dev extras
make mongo-up # MongoDB 7 single-node replica set in Docker
make check # ruff + mypy --strict + pytest
Integration tests skip when MongoDB isn't running. To test another MongoDB version, run
MONGO_VERSION=8.0 make mongo-up.
Releasing
- Bump
src/mongomig/_version.pyand updateCHANGELOG.md, then merge tomain. - Create a GitHub Release with tag
v<version>and publish it. The release workflow checks the version, builds and smoke-tests the wheel, and publishes to PyPI via Trusted Publishing.
Contributing
Bug reports, ideas and pull requests are welcome. See CONTRIBUTING.md.
License
MIT
Metadata
Release files for mongomig 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mongomig-0.4.1.tar.gz | 177.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mongomig-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 316.7 kB
Release files / mongomig-0.4.1.tar.gz
| Download URL | mongomig-0.4.1.tar.gz |
|---|---|
| Size | 177.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ecaf9df501c2383d171ff0f1ae70253c1032f8dff8c83ec185421664a7708dcb
|
|
BLAKE2b-256 checksum How to use checksums |
c6823faefe9897c1263f853fbdb2a9a72a5729aca42963bfa979e39398207127
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / mongomig-0.4.1-py3-none-any.whl
| Download URL | mongomig-0.4.1-py3-none-any.whl |
|---|---|
| Size | 138.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
247d886905f27495f90a66c42eb9ee6236986f52561158b700dc84abdb6f019b
|
|
BLAKE2b-256 checksum How to use checksums |
6671bbf35b8bfb4c5685e156eb0aac6a109a8d84cca7aed90740781cb771d671
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency log