VPS Snaps

How to back up Meilisearch

Meilisearch has two backups. A snapshot (--schedule-snapshot, or POST /snapshots) is a compressed copy of the database that imports fast but only into the exact same Meilisearch version; a dump (POST /dumps) is a portable export that rebuilds the indexes on import and moves to newer versions. Both restore only at launch, into an empty database, with --import-snapshot or --import-dump.

7 min readUpdated Checked against official documentation

Snapshots or dumps

The Community Edition is MIT licensed; 1.54.3, from October 1, 2026, is current. Meilisearch Cloud has no snapshots and makes dumps only through support; this guide is for self-hosted instances.

SnapshotDump
What it isCopy of the database files (data.ms), as .tar.gzExport of documents, settings, tasks and keys, as .tar.gz
ImportFast: unpacked as isSlow: every index is rebuilt
Restores intoThe same Meilisearch version onlyThe same or a newer version
File<database dir>.snapshot, replaced by each new snapshot<dumpUid>.dump, a new file each time
API keysIncluded, in the copied auth databaseIncluded without their secret values
Created by--schedule-snapshot or POST /snapshotsPOST /dumps

Use both: snapshots for quick recovery, a dump for upgrades and as the copy any later version can read. Neither contains the master key or the instance's configuration (/etc/meilisearch.toml or the Docker environment). Back those up encrypted: without the same master key, every API key changes.

Where the files go

Docker imageOfficial systemd setup
Database (--db-path, MEILI_DB_PATH)/meili_data/data.ms/var/lib/meilisearch/data
Dumps (--dump-dir, MEILI_DUMP_DIR)/meili_data/dumps/var/lib/meilisearch/dumps
Snapshots (--snapshot-dir, MEILI_SNAPSHOT_DIR)/meili_data/snapshots/var/lib/meilisearch/snapshots
Snapshot filedata.ms.snapshotdata.snapshot

Both snapshots and dumps are first staged in TMPDIR (/tmp by default), not in their own directory. If /tmp is small, set TMPDIR to an existing directory on a disk with room for a full copy of the database. Run the image with a pinned tag and the settings in a root-only env file:

/etc/meilisearch.env
MEILI_ENV=production
MEILI_MASTER_KEY=a-long-random-master-key
MEILI_SCHEDULE_SNAPSHOT=86400
Terminal
docker run -d --name meilisearch --restart unless-stopped -p 127.0.0.1:7700:7700 --env-file /etc/meilisearch.env -v /srv/meili_data:/meili_data getmeili/meilisearch:v1.54.3

MEILI_SCHEDULE_SNAPSHOT=86400 takes a snapshot every 86,400 seconds (24 hours); the environment variable must be a number of seconds. The first snapshot comes one interval after launch. On the command line, --schedule-snapshot with no value means 24 hours; in the TOML config file, schedule_snapshot = 86400 or true.

Each snapshot replaces the previous file, so the directory only ever holds one, and a damaged database can be snapshotted over your good copy. Copy it to a dated name elsewhere, as the script below does. Snapshots to S3 (--s3-bucket-url and related options) need the Enterprise Edition.

Create a key for backups

Keep the master key for managing keys, and give the backup script its own key with only the actions it needs:

Terminal
curl -fsS -X POST "http://127.0.0.1:7700/keys" -H "Authorization: Bearer MASTER_KEY" -H "Content-Type: application/json" --data-binary '{"description": "Backups", "actions": ["dumps.create", "snapshots.create", "tasks.get", "stats.get"], "indexes": ["*"], "expiresAt": null}'

Copy the key from the reply into a file only root can read (chmod 600). expiresAt is required; null means it never expires. MEILI_SNAPSHOT and MEILI_DUMPS are host paths, so for the systemd setup use /var/lib/meilisearch/snapshots/data.snapshot and /var/lib/meilisearch/dumps:

/etc/meili-backup.env
MEILI_URL=http://127.0.0.1:7700
MEILI_BACKUP_KEY=the-key-from-the-reply
MEILI_SNAPSHOT=/srv/meili_data/snapshots/data.ms.snapshot
MEILI_DUMPS=/srv/meili_data/dumps

Create a dump and wait for it

Terminal
curl -fsS -X POST "$MEILI_URL/dumps" -H "Authorization: Bearer $MEILI_BACKUP_KEY"

The reply is a task with "status": "enqueued" and a taskUid. Dumps and snapshots go through the same queue as indexing, so they wait for earlier tasks. Poll the task:

Terminal
curl -fsS "$MEILI_URL/tasks/42" -H "Authorization: Bearer $MEILI_BACKUP_KEY"

status moves from enqueued to processing, then succeeded, failed (with the reason in error) or canceled. On success, details.dumpUid, such as 20261004-023012345, names the file 20261004-023012345.dump in the dump directory. Meilisearch never leaves a partial dump file. POST /snapshots works the same way.

Run it every night

This script takes a snapshot and a dump, waits for each, keeps dated copies in /var/backups/meilisearch, tests the dump's gzip stream and deletes copies older than two days. It needs jq. On a large instance, run the dump half weekly.

/usr/local/bin/meili-backup.sh
#!/bin/bash
set -euo pipefail
. /etc/meili-backup.env
AUTH="Authorization: Bearer $MEILI_BACKUP_KEY"
DEST=/var/backups/meilisearch
STAMP=$(date +%F-%H%M)
mkdir -p "$DEST"

wait_task() {
  local status
  while true; do
    status=$(curl -fsS -H "$AUTH" "$MEILI_URL/tasks/$1" | jq -r '.status')
    case "$status" in
      succeeded) return 0 ;;
      enqueued|processing) sleep 15 ;;
      *) echo "$(date -Is) task $1 $status" >&2
         curl -fsS -H "$AUTH" "$MEILI_URL/tasks/$1" | jq -c '.error' >&2
         return 1 ;;
    esac
  done
}

uid=$(curl -fsS -X POST -H "$AUTH" "$MEILI_URL/snapshots" | jq -r '.taskUid')
wait_task "$uid"
cp "$MEILI_SNAPSHOT" "$DEST/snapshot-$STAMP.snapshot"

uid=$(curl -fsS -X POST -H "$AUTH" "$MEILI_URL/dumps" | jq -r '.taskUid')
wait_task "$uid"
dump=$(curl -fsS -H "$AUTH" "$MEILI_URL/tasks/$uid" | jq -r '.details.dumpUid')
mv "$MEILI_DUMPS/$dump.dump" "$DEST/"
gzip -t "$DEST/$dump.dump"

find "$DEST" -type f -mtime +1 -delete
echo "$(date -Is) saved snapshot-$STAMP and $dump.dump"
Terminal
sudo chmod 700 /usr/local/bin/meili-backup.sh
/etc/cron.d/meili-backup
30 2 * * * root /usr/local/bin/meili-backup.sh >> /var/log/meili-backup.log 2>&1

To see which version wrote a dump, print its metadata: tar -xzOf 20261004-023012345.dump --wildcards '*metadata.json' shows dbVersion. Then copy the directory off the server (3-2-1 rule); cron schedules covers failure alerts.

Restore on a new server

Use the same MEILI_MASTER_KEY. An API key's secret is derived from its uid and the master key, so with the same master key every restored key keeps its value and your applications keep working. The database directory must not exist yet. For a snapshot, run the exact same image tag:

Terminal
sudo mkdir -p /srv/meili_data/snapshots
Terminal
sudo cp snapshot-2026-10-04-0230.snapshot /srv/meili_data/snapshots/
Terminal
docker run -d --name meilisearch -p 127.0.0.1:7700:7700 --env-file /etc/meilisearch.env -v /srv/meili_data:/meili_data getmeili/meilisearch:v1.54.3 meilisearch --import-snapshot /meili_data/snapshots/snapshot-2026-10-04-0230.snapshot

A dump restores into the same or a newer version: copy it under /srv/meili_data/dumps and replace the last argument with --import-dump /meili_data/dumps/20261004-023012345.dump. Meilisearch rebuilds every index before it accepts requests; follow docker logs -f meilisearch until it is listening.

  • Compare counts with the old server: curl -fsS -H "Authorization: Bearer $MEILI_BACKUP_KEY" http://127.0.0.1:7700/stats | jq '.indexes | map_values(.numberOfDocuments)'.
  • Once it is running, remove the container (docker rm -f meilisearch) and start it again with the normal command, without the import flag. Left in place, the next restart fails because the database now exists.
  • With the systemd setup: stop the service, move /var/lib/meilisearch/data aside, run sudo -u meilisearch /usr/local/bin/meilisearch --config-file-path /etc/meilisearch.toml --import-dump <file> in the foreground, press Ctrl+C once it is listening, then systemctl start meilisearch.

Restore into a spare server every month and time it: that is your real recovery time (testing restores).

Before upgrading

A newer binary refuses an older database until you start it with --upgrade-db (MEILI_UPGRADE_DB; before 1.51 it was --experimental-dumpless-upgrade). The docs warn the upgrade is not atomic and can corrupt the database, so take a snapshot first and keep the old image tag to roll back to. Databases from versions older than 1.12 can't be upgraded this way: create a dump with the old version and import it into the new one.

Common errors

ErrorFix
database already exists at "/meili_data/data.ms", try to delete it or rename itAn import flag with an existing database. Move data.ms aside, or drop the flag after the first import.
snapshot doesn't exist at /meili_data/snapshots/... or dump doesn't exist at "..."The path is read inside the container. Check the volume and use the /meili_data/... path.
Your database version (1.53.3) is incompatible with your current engine version (1.54.3).The image tag changed. Go back to the old tag, or snapshot and start with --upgrade-db, or import a dump.
Launch fails: the database version is too old to be upgraded via --upgrade-dbThe database predates 1.12. Reinstall its version, create a dump, import it into the new one.
No space left on device during a snapshot or dumpTMPDIR is too small. Point it at a larger disk.
The Authorization header is missing. It must use the bearer authorization method.Send Authorization: Bearer <key>.
The provided API key is invalid.Wrong key, or the master key changed since it was created.
processing an S3-streaming snapshot task requires the Enterprise EditionS3 snapshots need the Enterprise Edition. Write snapshots to disk and copy them.

Frequently asked questions

What is the difference between a Meilisearch dump and a snapshot?
A snapshot is a copy of the database files: fast to import, but only into the exact same version. A dump is an export that rebuilds the indexes on import and works in the same or a newer version.
Does a Meilisearch dump include API keys?
Yes, without their secret values. Each key's value is derived from its uid and the master key, so importing with the same master key gives the same key values.
Can I import a dump into a running Meilisearch?
No. Dumps and snapshots import only at launch, with --import-dump or --import-snapshot, into an empty database directory.
Where does Meilisearch in Docker save dumps and snapshots?
In /meili_data/dumps and /meili_data/snapshots inside the container, so in the volume you mount at /meili_data.
Why is there only one Meilisearch snapshot file?
Each new snapshot replaces the previous file. Copy it to a dated name after each run if you want history.

How this was checked

Commands, limits and prices were checked against these official pages, on October 4, 2026: