Appearance
Backup & restore
Because everything lives in MongoDB, backup is refreshingly simple — one database snapshot captures your whole platform. The single thing that lives outside the database is your SECRETS_KEY, and it needs its own backup.
One snapshot covers everything
FlowRunner keeps all state in Mongo — including uploaded files, which are stored in GridFS rather than on a separate object store. So a single mongodump (or Atlas continuous backup) captures the lot:
| What | Where it lives |
|---|---|
| Projects & designs | projects |
| Edit history | project_history |
| Form submissions | submissions |
| Encrypted secrets | secrets (ciphertext only) |
| Uploaded files | uploads.files + uploads.chunks (GridFS) |
| Flow run history | flow_runs |
| Schedules | schedules |
| Custom domains | domains |
bash
# Back up the entire database
mongodump --uri="$MONGODB_URI" --out=./backup-$(date +%F)
# Restore it
mongorestore --uri="$MONGODB_URI" ./backup-2026-07-18TIP
If you're on MongoDB Atlas, its continuous / point-in-time backup covers all of the above with no mongodump schedule to maintain. Either approach captures GridFS uploads, since they're just Mongo collections.
The SECRETS_KEY caveat
There is exactly one thing a database backup does not protect you against.
The secrets collection stores only ciphertext. Those secrets are encrypted with SECRETS_KEY, which lives in your environment, not in Mongo. A database restore brings back the encrypted blobs — but they are only decryptable with the same SECRETS_KEY that encrypted them.
WARNING
Back up SECRETS_KEY separately from the database — in a password manager or a secrets store, not in the same snapshot. If you lose or rotate the key, every existing secret is stranded: the ciphertext survives the restore but can no longer be decrypted, and workspace secrets must be re-entered by hand.
This separation is a feature, not a hazard: it means a leaked database dump reveals no usable secrets. Keeping the key elsewhere preserves that guarantee. See Secrets and Environment variables.
Data lifecycle
Some collections manage their own size, so you don't have to back up or prune them the same way:
| Collection | Behaviour |
|---|---|
flow_runs (run history) | Self-expires after 30 days via a TTL index on its timestamp. Rows older than that are removed automatically. |
ratelimits | Short-lived counters with their own TTL. Safe to drop entirely — they rebuild on demand. |
project_history | Grows with every edit. It never auto-prunes; if it gets large, trim old revisions. |
NOTE
The 30-day run-history window is a retention policy, not a backup. If you need long-term audit records of flow runs, export them before they expire. Everything else in the tables above is durable until you delete it.
A practical backup routine
- Take a database snapshot on a schedule (
mongodumpcron, or enable Atlas continuous backup). - Store
SECRETS_KEYin a separate secrets manager, versioned alongside your other environment secrets. - Periodically test a restore into a throwaway database and confirm
GET /api/healthreturns200against it.