Schedule icon
Aggregate icon
Commands icon
Upload icon
Download icon
OutputValues icon
If icon
Copy icon
Log icon
SlackIncomingWebhook icon
Delete icon
Fail icon
Delete icon

Back up a MongoDB collection and prove it restores, every night

Nightly mongodump to S3 or MinIO with a restore drill. Kestra restores each archive, checks documents and indexes, then promotes only verified backups.

Categories
DataInfrastructure

A backup you have never restored is a guess. This flow dumps one MongoDB collection with mongodump, uploads the archive to S3-compatible storage, downloads it back, and restores it into a scratch database with mongorestore. It promotes the archive to a stable latest-good key only when every dumped document came back, none failed to restore and the indexes match the source. A failed drill deletes the bad archive, keeps the last good one and ends the run red.

The check compares the archive with its own restore, not with the live collection, so writes during the backup do not cause false alarms.

This blueprint was created by zkasuran.

How it works

  1. source_indexes (io.kestra.plugin.mongodb.Aggregate, $indexStats) lists the index names on the source collection.
  2. dump (io.kestra.plugin.scripts.shell.Commands, mongo:8.0 image) runs mongodump --archive --gzip. It keeps BSON types such as ObjectId and Decimal128 plus the index definitions, and outputs the dumped document count. A collection that does not exist fails here with a clear message.
  3. upload_archive (io.kestra.plugin.minio.Upload) writes the archive under archives/<db>.<collection>/<timestamp>.archive.gz.
  4. download_archive (io.kestra.plugin.minio.Download) reads the stored object back, so the drill tests what is in the bucket.
  5. restore runs mongorestore --drop into <restore_database>.<collection> and outputs the number of failed documents.
  6. restored_count and restored_indexes (io.kestra.plugin.mongodb.Aggregate) count the restored documents and list its indexes. drill (io.kestra.plugin.core.output.OutputValues) collects the numbers.
  7. restore_gate (io.kestra.plugin.core.flow.If) passes when restored equals dumped, failed is 0, the index names match and the dump has at least min_documents documents.
    • Pass: promote_archive (io.kestra.plugin.minio.Copy) copies the archive to verified/<db>.<collection>/latest-good.archive.gz.
    • Fail: discard_archive (io.kestra.plugin.minio.Delete) removes the archive and fail_run (io.kestra.plugin.core.execution.Fail) ends the run as FAILED.
  8. errors posts an alert when a task fails before the drill decides, for example when MongoDB or the bucket is unreachable. finally empties the scratch copy on every run.

Inputs

  • database (STRING, default ecommerce): source database.
  • collection (STRING, default orders): source collection.
  • bucket (STRING, default mongo-backups): target bucket, which must exist.
  • restore_database (STRING, default restore_check): scratch database for the drill. Never use a production database here.
  • min_documents (INT, default 1): a smaller dump fails the drill. Set it near your normal size to catch an emptied collection.
  • notify_slack (BOOL, default false): post results to Slack.

Prerequisites

  • A Kestra worker that can run Docker containers. The dump and restore tasks use the official mongo:8.0 image.
  • A MongoDB user that can read the source collection, run $indexStats, and write to restore_database.
  • An S3-compatible store (MinIO, AWS S3, Ceph, SeaweedFS) with the target bucket.

Secrets

  • MONGODB_URI: MongoDB connection string used for the dump, the restore and the checks.
  • MINIO_ENDPOINT: object store endpoint, for example https://s3.example.com.
  • MINIO_ACCESS_KEY_ID: object store access key.
  • MINIO_SECRET_KEY_ID: object store secret key.
  • SLACK_WEBHOOK_URL: Slack incoming webhook. Only needed when notify_slack is true.

Quick start

  1. Add the secrets and create the bucket.
  2. Set database and collection, then run the flow once. The log shows Restore drill passed with the document count and index names.
  3. Run it with min_documents set above the collection size to watch the drill fail, delete the archive and keep latest-good.
  4. Leave the nightly schedule on.

Expected outputs

  • outputs.drill.values.dumped and outputs.drill.values.restored: document counts.
  • outputs.drill.values.restored_indexes: the index names that came back.
  • s3://<bucket>/verified/<db>.<collection>/latest-good.archive.gz: the last archive that passed. Restore it with mongorestore --archive=latest-good.archive.gz --gzip.

How to extend

  • Back up several collections with io.kestra.plugin.core.flow.ForEach over a list and a subflow holding this logic.
  • Add an S3 lifecycle rule on archives/ to expire old archives.
  • Compare a field checksum between source and restore with a second Aggregate for a stricter drill.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.