Skip to content
DevOps devops databases 5 min read

Backing Up & Restoring MongoDB

A backup is a saved copy of your data that you can use to get back to a working state after a disaster — a crashed disk, a bad deploy, an accidental db.dropDatabase(), or a ransomware attack. MongoDB is a document database (it stores flexible JSON-like records instead of rows and tables), and it ships with two dedicated backup tools: mongodump and mongorestore. This page shows you exactly how to use them on Ubuntu, how to schedule them, and — most importantly — how to test that your backups actually work.

How mongodump works

mongodump connects to a running MongoDB server and writes its data to disk in BSON format. BSON (Binary JSON) is the binary form that MongoDB uses internally to store documents, so a mongodump backup is a faithful, lossless copy of your data — including data types like dates and ObjectIds that plain JSON cannot represent perfectly.

The output is a directory tree. Each database becomes a folder, and each collection (a collection is MongoDB’s equivalent of a table) becomes a .bson file plus a .metadata.json file that records its indexes.

When to use this: mongodump/mongorestore is the right tool for small-to-medium databases (up to roughly tens of GB) and for moving data between servers. When NOT to use it: for very large or busy production clusters, prefer filesystem/volume snapshots or MongoDB’s continuous backup features — mongodump reads the whole dataset and can put load on a live server.

On Ubuntu, these tools are not in the server package. Install the MongoDB Database Tools:

sudo apt update
sudo apt install -y mongodb-database-tools
mongodump --version

Output:

mongodump version: 100.10.0
git version: a1b2c3d4e5f6...
Go version: go1.22.5

Authentication flags

If you enabled authentication (a login system requiring a username and password — covered in MongoDB users & authentication), every dump and restore must log in. The important flags are:

FlagMeaning
-u / --usernameThe MongoDB user
-p / --passwordThat user’s password
--authenticationDatabaseThe database where the user was created — almost always admin
--host / --portWhere the server is (default localhost:27017)
--uriA full connection string instead of separate flags

Passing -p secret on the command line leaves your password visible in your shell history and in the process list (ps aux). Omit the value (-p) to be prompted interactively, or store credentials in a --uri read from a 0600-permission file.

Taking a full backup

This dumps every database the user can read into a timestamped directory:

mongodump \
  --uri="mongodb://localhost:27017" \
  -u backupAdmin \
  --authenticationDatabase admin \
  -p \
  --out /var/backups/mongo/full-$(date +%F)

Output:

Enter password:
2026-06-15T02:00:01.114+0000	writing admin.system.users to /var/backups/mongo/full-2026-06-15/admin/system.users.bson
2026-06-15T02:00:01.230+0000	writing shop.products to /var/backups/mongo/full-2026-06-15/shop/products.bson
2026-06-15T02:00:01.488+0000	done dumping shop.products (1452 documents)

Backing up a single database

Use --db to dump just one database, and --gzip to compress every file:

mongodump \
  --db shop \
  --gzip \
  -u backupAdmin --authenticationDatabase admin -p \
  --out /var/backups/mongo/shop-$(date +%F)

You can narrow it further with --collection products for a single collection, or --archive=/path/file.archive to write one file instead of a folder tree.

Restoring with mongorestore

mongorestore reads a dump directory (or archive) and writes the documents back into a server. The most common mistake is assuming it deletes existing data first — it does not. By default it inserts documents and skips ones whose _id already exists.

Restore the single-database dump from above:

mongorestore \
  --db shop \
  --gzip \
  -u backupAdmin --authenticationDatabase admin -p \
  /var/backups/mongo/shop-2026-06-15/shop

Output:

2026-06-15T09:12:00.501+0000	preparing collections to restore from
2026-06-15T09:12:00.640+0000	restoring shop.products from .../products.bson.gz
2026-06-15T09:12:01.902+0000	finished restoring shop.products (1452 documents, 0 failures)
2026-06-15T09:12:01.903+0000	1452 document(s) restored successfully. 0 document(s) failed to restore.

Two flags change this behaviour:

  • --drop — drop each collection before restoring it, so the result exactly matches the dump (use this when restoring after corruption).
  • --nsFrom/--nsTo — rename databases or collections during restore, e.g. restore shop into shop_test.
mongorestore --gzip --drop --nsFrom 'shop.*' --nsTo 'shop_test.*' \
  -u backupAdmin --authenticationDatabase admin -p \
  /var/backups/mongo/shop-2026-06-15

mongoexport and mongoimport

mongodump produces BSON that only MongoDB understands. When you need human-readable JSON or CSV — for a report, a spreadsheet, or feeding data to another tool — use mongoexport and mongoimport instead.

# Export one collection to JSON
mongoexport --db shop --collection products \
  -u backupAdmin --authenticationDatabase admin -p \
  --out products.json

# Export selected fields to CSV
mongoexport --db shop --collection products --type=csv \
  --fields name,price,sku -p -u backupAdmin --authenticationDatabase admin \
  --out products.csv

# Import JSON back
mongoimport --db shop --collection products --file products.json \
  -u backupAdmin --authenticationDatabase admin -p

mongoexport/mongoimport are not a faithful backup. JSON cannot represent every BSON type cleanly, so dates and binary fields can change. Use them for data interchange, never as your disaster-recovery copy. For that, always use mongodump.

A scheduled backup script

Create /usr/local/bin/mongo-backup.sh:

#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/var/backups/mongo"
KEEP_DAYS=14
STAMP="$(date +%F_%H-%M)"
URI="mongodb://localhost:27017"

mkdir -p "$BACKUP_DIR"

mongodump \
  --uri="$URI" \
  -u backupAdmin --authenticationDatabase admin \
  -p "$(cat /etc/mongo-backup.pw)" \
  --gzip \
  --archive="$BACKUP_DIR/all-$STAMP.archive"

# Delete archives older than KEEP_DAYS
find "$BACKUP_DIR" -name 'all-*.archive' -mtime +"$KEEP_DAYS" -delete

Store the password in a locked-down file, make the script executable, then schedule it with systemd or cron:

echo 'your-strong-password' | sudo tee /etc/mongo-backup.pw
sudo chmod 600 /etc/mongo-backup.pw
sudo chmod +x /usr/local/bin/mongo-backup.sh

# Run every night at 02:00 via root's crontab
echo '0 2 * * * /usr/local/bin/mongo-backup.sh >> /var/log/mongo-backup.log 2>&1' \
  | sudo tee /etc/cron.d/mongo-backup

See Automating database backups for off-server copies and retention strategy.

Always test your restores

A backup you have never restored is not a backup — it is a hope. Schedule a real restore into a throwaway database and check the document counts match:

LATEST=$(ls -t /var/backups/mongo/all-*.archive | head -1)
mongorestore --gzip --archive="$LATEST" --drop \
  --nsFrom '*' --nsTo 'restoretest_*' \
  -u backupAdmin --authenticationDatabase admin -p

Then connect with mongosh and run db.products.countDocuments() against the restored copy to confirm the data is intact, and drop the test databases afterwards.

Best Practices

  • Use mongodump --gzip --archive for compact, single-file backups that are easy to copy off-server.
  • Never store the password inline in scripts or cron lines — read it from a chmod 600 file owned by root.
  • Run a dedicated backup user with only the backup and restore roles, not full admin rights.
  • Copy backups off the database server (S3, another host) — a local backup dies with the disk it lives on.
  • Test a restore on a schedule and verify document counts, not just that the command exits 0.
  • Use mongodump/mongorestore for portability and small datasets; switch to volume snapshots for large, busy clusters.
Last updated June 15, 2026
Was this helpful?