RE:NODE
ჰოსტინგი

ბაზები12 წუთის საკითხავი

mongodump and mongorestore: backups that restore

How to back up MongoDB properly: mongodump options, archives and gzip, why a dump is not point-in-time, restoring one collection, and scheduling that works.

ეს სტატია ჯერ ინგლისურადაა. ვთარგმნით.

0 მკითხველი

The short version is two commands. mongodump --uri="$MONGODB_URI" --archive=shop-2026-09-21.gz --gzip writes every collection into one compressed file while the server keeps serving. mongorestore --uri="$MONGODB_URI" --archive=shop-2026-09-21.gz --gzip --drop puts it back. Both are separate programs from the database, both take their connection details the same way your application does, and neither takes the server offline.

The longer version is the part that decides whether you still have your data in a year. A mongodump is a logical backup: a copy of the documents, read out through ordinary queries. That makes it portable across versions and machines, and it also means it is not an instant. On a standalone server the dump reads one collection after another while writes continue underneath it, so the archive is internally consistent per collection and not across them. Knowing exactly what that does and does not guarantee is most of this post.

What mongodump produces, and where to get it#

Since MongoDB 4.4 the tools are not bundled with the server. mongodump, mongorestore, mongoexport, mongoimport and bsondump ship as the MongoDB Database Tools, a separate package with its own version numbers in the 100.x series. Install them on whichever machine is going to take the backups - your application server, your laptop, wherever your scheduler runs - and they will talk to the database over the same host and port as your application does.

By default, mongodump writes a directory:

code
dump/  shop/    orders.bson    orders.metadata.json    customers.bson    customers.metadata.json

Each .bson file is the raw documents in binary. Each .metadata.json holds the collection options and the index definitions, which is how mongorestore knows to rebuild your indexes afterwards. Delete a metadata file and you restore the data without its indexes, which is an expensive mistake to discover in production.

--archive replaces that directory with a single stream, which is what you almost always want: one file to name, move, checksum and download. --archive with no filename writes to standard output, so a dump can be piped straight into a restore on another machine without touching disk on either.

Taking a dump#

bash
$ mongodump --uri="mongodb://backup:pw@db.example.net:27017/?authSource=admin" \      --db=shop \      --archive="shop-$(date +%F).gz" --gzip

Connection details come from --uri or from the individual flags (--host, --port, -u, -p, --authenticationDatabase), not both at once. The user needs the backup role, which is exactly the set of privileges the tool requires and nothing more. If you are still working out what the URI should look like, MongoDB connection strings takes one apart.

OptionDefaultWhat it does
--db, --collectionallRestrict what is dumped
--archive=FILEdirectory outputOne file instead of a folder
--gzipoffCompress; often a quarter of the size
--out=DIRdump/Where directory output goes
--query='{...}'noneDump a subset; needs --collection
--excludeCollectionnoneSkip a collection, repeatable
--numParallelCollections4Collections dumped at once
--readPreferenceprimaryRead from a secondary instead
--oplogoffReplica sets only, see below
--dumpDbUsersAndRolesoffInclude users defined in this database

Two of those are worth a second look. --query turns a dump into an export of part of a collection, which is how you pull one customer's data out for a support request without copying 40 GB. And --numParallelCollections=4 is the default because four workers saturate most small servers; on a 1 GB plan, lowering it to 1 makes the dump slower and the database noticeably less unhappy while it runs.

Users and roles are not included unless you ask. They are stored in admin.system.users and admin.system.roles, so either dump the admin database as well or use --dumpDbUsersAndRoles with --db. A restore that succeeds and then refuses every login is usually this.

Consistency: the thing everyone gets wrong#

mongodump reads collections sequentially. If it starts at 02:00 and finishes at 02:06, users.bson reflects 02:00 and orders.bson reflects 02:06. An order written at 02:03 referencing a user created at 02:03 can land in the archive with the order present and the user missing. For most applications that is a theoretical problem; for anything where a dangling reference breaks a screen, it is not.

replica set onlyreplays the gapDump starts02:00users.bsonread at 02:00orders.bsonread at 02:06oplog.bson02:00 to 02:06Restore--oplogReplay
Why --oplog is what makes a dump a single point in time

The fix is --oplog, which additionally captures the operation log for the window the dump covers. Restoring with --oplogReplay then applies those operations on top, bringing every collection to the same instant: the moment the dump finished. It has two requirements that rule it out for many people. It needs a replica set, because a standalone mongod has no oplog at all, and it dumps the whole instance, so it cannot be combined with --db or --collection.

On a single standalone server, then, your honest options are: accept per-collection consistency, which is fine for the large majority of applications; stop writes for the duration, which is realistic for a small database that dumps in twenty seconds; or run the instance as a single-member replica set so that an oplog exists. The one thing not to do is assume you have point-in-time recovery because you have a nightly dump. You do not, and the moment to discover that is not during an incident. The same distinction applies in the relational world - pg_dump and pg_restore draws the same line between a logical dump and true point-in-time recovery.

Restoring#

bash
$ mongorestore --uri="mongodb://root:pw@db.example.net:27017/?authSource=admin" \      --archive=shop-2026-09-21.gz --gzip --drop
OptionWhat it does
--dropDrops each collection in the dump before restoring it
--nsInclude, --nsExcludeRestore only, or all but, matching namespaces
--nsFrom, --nsToRename databases or collections during the restore
--noIndexRestoreSkip index builds, usually a bad idea
--numParallelCollectionsCollections restored at once, default 4
--numInsertionWorkersPerCollectionDefault 1; raise for one huge collection
--stopOnErrorAbort on the first failure instead of continuing
--oplogReplayApply oplog.bson after the data, for --oplog dumps
--preserveUUIDKeep collection UUIDs; requires --drop
--writeConcernLower it during a bulk load

The nuance in --drop catches everybody at least once. It drops the collections that are in the dump. It does not touch collections that exist on the target but not in the archive, so a restore into a dirty database leaves stale collections behind and looks like it worked. If you want a clean result, drop the database first, or restore into a fresh one.

Index rebuilding is normally the slowest part of the restore, because every index is built from scratch after the documents land. That is also why a restored database is often faster than the one it came from: the indexes come out fresh rather than fragmented. Do not reach for --noIndexRestore to speed things up unless you are going to build the indexes yourself immediately afterwards - the application will be unusable until you do. MongoDB schema design and indexes covers what those builds are doing.

Before restoring anything you are not sure about, look inside it. bsondump --quiet dump/shop/orders.bson | head -n 3 prints the first few documents as JSON, and for an archive you can restore into a scratch database and count instead:

bash
$ mongorestore --archive=shop-2026-09-21.gz --gzip \      --nsFrom='shop.*' --nsTo='shop_check.*'$ mongosh --quiet --eval 'db.getSiblingDB("shop_check").orders.countDocuments()'

Restoring one collection, or into another name#

The common emergency is not "the server is gone". It is "somebody ran a delete without a filter on one collection at 11:40". You want that collection back, from last night, with everything else untouched.

bash
$ mongorestore --archive=shop-2026-09-21.gz --gzip \      --nsInclude='shop.orders' --drop

--nsInclude accepts patterns, so --nsInclude='shop.*' restores one database out of a whole-instance archive. The safer version of the same operation restores beside the live data instead of over it, so that you can compare before you commit:

bash
$ mongorestore --archive=shop-2026-09-21.gz --gzip \      --nsInclude='shop.orders' \      --nsFrom='shop.orders' --nsTo='rescue.orders'

Now rescue.orders holds last night's copy. Count it, spot-check a few documents, work out which ones are missing from the live collection, and copy only those across with an aggregation and $merge. That is slower than --drop and it does not throw away the writes that happened between the backup and the mistake, which is usually what you actually want.

--nsFrom and --nsTo are also how you create a staging copy: restore production's archive into a database called shop_staging on another server and point staging at it. Do that on a different server, not the production one, unless you enjoy discovering that a restore filled the disk.

mongoexport and mongoimport are not backups#

mongoexport writes JSON or CSV. It is genuinely useful for handing data to somebody with a spreadsheet, or for loading a fixture. It is not a backup, for one specific reason: by default it writes relaxed extended JSON, which does not round-trip BSON types. A 64-bit integer can come back as a double, a Decimal128 loses precision, and dates and object identifiers become ambiguous. --jsonFormat=canonical preserves the types, but the output is still larger, slower and missing your index definitions.

The rule is simple. mongodump and mongorestore for backups and moves between MongoDB instances, because they carry BSON types and metadata faithfully. mongoexport and mongoimport for interchange with anything that is not MongoDB.

The other kinds of backup, and their trade-offs#

Filesystem or volume snapshots. Fast and whole-instance, but only valid if the snapshot is atomic across every volume holding the data and the journal. Two volumes snapshotted a second apart give you a database that may not start. Where you cannot guarantee atomicity, db.fsyncLock() flushes and blocks writes for the duration, which is a real outage however short.

Copying the data directory of a running server. Not a backup. The files are being written while you copy them, and the result is a corrupt database that will look fine until it is the only copy you have.

Your host's backup slots. These protect the whole server, take seconds to trigger, and are the right thing for "the server broke". On RE:NODE every database plan includes backup slots, taken on demand or on a schedule, stored off the machine they protect, restored with a button, downloadable, and lockable so rotation cannot remove the one you are relying on. The honest limitation is in the fine print of every platform: deleting a server deletes its backups, locked ones included. So keep a mongodump archive downloaded somewhere else as well. Two mechanisms that fail differently is the whole point - backups that actually restore makes the same argument at more length.

Scheduling, retention and disk headroom#

The routine that works, and it is the same one for every database:

  1. Dump nightly at the quietest hour, with the date in the filename, compressed.
  2. Move the archive off the machine it came from. A dump on the same disk protects you from a bad query and nothing else.
  3. Keep seven daily and four weekly copies, and prune automatically. Manual pruning ends in a full disk, and a database server with a full disk stops accepting writes.
  4. Once a quarter, restore the newest archive into a scratch database, count documents in the collections you care about, point a copy of the application at it, and drop it.

Step four is the one everybody skips, and it is the only one that turns a file into a backup. Testing a restore before you need it and backing up a database and proving it restores exist because of how often step four is skipped.

The Schedules tab in the panel takes a cron expression and runs ordered tasks with delays between them - a backup, a power action - so the nightly platform-side backup is configuration rather than a script you have to keep alive. The mongodump half belongs wherever your application or your scheduler runs, pointed at the database's host and port. The panel guides cover where those controls are.

Watch the disk. A dump written to the database server's own storage needs room for the compressed archive on top of the data and indexes, and on a 20 GB plan with 12 GB in use there may not be any. Write the archive somewhere else, or stream it: mongodump --archive --gzip | ssh backup-host 'cat > shop.gz' never puts the file on the database server at all.

Errors you will actually see#

`Failed: error connecting to db server` - a connection problem, not a backup problem. Wrong host or port, the server bound to the loopback address only, or a firewall. Try the same URI in mongosh first.

`Failed: ... Authentication failed` - usually the missing --authenticationDatabase admin, which is the same authSource question the drivers ask.

`E11000 duplicate key error collection` - restoring into a collection that already has those documents. You wanted --drop, or a fresh database.

`Failed: restore error: ... oplog.bson: no such file` - --oplogReplay on a dump taken without --oplog. The oplog is only there if you asked for it at dump time.

`Failed: cannot use --oplog with --db or --collection` - --oplog is all or nothing across the instance.

A restore that finishes with no indexes - the metadata files were lost, or --noIndexRestore was set. Rebuild them from your schema definitions.

A restore that runs out of memory or disk - index builds and parallel insertion both cost memory. Lower --numParallelCollections, and check that the target has room for data plus indexes, which is more than the size of the compressed archive suggests.

FAQ#

Does mongodump lock the database?

No. It reads through the normal query path, so the server keeps serving. It does compete for CPU, memory and disk throughput, which on a small instance is noticeable, so run it when the application is quiet and consider lowering --numParallelCollections.

Is a mongodump a point-in-time backup?

Only with --oplog on a replica set, restored with --oplogReplay. Without it, each collection is consistent within itself but the collections are read at slightly different times. For most applications that is acceptable; decide deliberately rather than by assumption.

Can I restore a dump into a newer MongoDB version?

Usually yes - BSON documents are portable, and that is the standard way to move between versions. Older dumps restored into much newer servers occasionally hit index options that have since changed; --convertLegacyIndexes exists for exactly that case. Restoring into an older major version than the dump came from is not something to rely on.

How do I restore just one collection?

mongorestore --archive=file.gz --gzip --nsInclude='db.collection'. If the live collection still has data you want to keep, restore into a different name with --nsFrom and --nsTo and merge, rather than dropping the live one.

mongodump or my host's backup button?

Both, because they fail differently. The platform backup restores the whole server quickly and disappears with the server. A mongodump archive you have downloaded is portable to any host and any supported version. Neither alone is a backup strategy.

How long does a restore take?

Loading the documents is roughly as fast as your disk and memory allow; rebuilding the indexes usually takes longer than that. A few gigabytes on NVMe is minutes. If you need a number you can promise somebody, measure it on your own data during a restore drill, because that is the only figure that means anything.


კომენტარები

სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.

0/2000