Declaring volume consistency¶
Your backup hook dumps your database. The manager reads your project's named volumes. Between them they cover the deployment — but only one of you knows whether a volume can be read while your product is writing to it, and it is not the manager.
That is what backup.volumes is for. It is a small declaration with a
disproportionate consequence, so this page is mostly about what you are
claiming.
The default needs no declaration¶
Every named volume in your Compose project is captured. A volume you say nothing about is captured cold: the manager stops the services that mount it, copies it, and starts them again.
That is correct for every volume, and slow for some. If your product's deployment is fine with a short stop during a nightly backup, you can ship nothing at all and it will work.
What hot means¶
backup:
volumes:
uploads: { consistency: hot }
caddy_data: { consistency: hot }
pgdata: { consistency: exclude }
consistency: hot says: a copy of this volume taken while my product is
running is a usable copy.
Copying a live volume gives a crash-consistent copy — byte-for-byte what a power cut would have left. So the question you are answering is: would my product come up correctly from this volume if the machine had lost power at an arbitrary instant?
Usually hot |
Never hot |
|---|---|
| Uploaded files written once and never modified | Anything with a write-ahead log — Postgres, MySQL, MongoDB, etcd |
| Generated thumbnails and other derived artifacts | A search index that is written incrementally |
| A certificate store written by an ACME client | A queue whose spool assumes ordered writes |
| Static assets extracted at build time | Anything you would not kill -9 and restart |
The test that catches most of it: if this volume is half-written, does my
product notice and repair it, or does it silently serve corrupt data? The first
is hot. The second is not, however convenient it would be.
hot is a claim you make about your own product
It is recorded in every backup manifest taken under it. If an operator ever has to explain why a restore did not work, the manifest says which volumes were copied live and on whose word.
When you are not sure, say nothing. The default is correct; it is only slow.
What exclude means¶
consistency: exclude keeps the manager out of a volume entirely — nothing is
copied and nothing is restored.
This is the expected declaration for your database's storage. Your backup hook already dumps it properly, and a second copy taken by other means is a copy somebody could restore instead of the good one.
backup:
volumes:
pgdata: { consistency: exclude }
Excluded volumes are reported to the operator — in the backup manifest and in
morzer doctor — so nobody is left believing a volume is covered when it is
not.
What it costs the operator¶
Before you leave a volume undeclared, know what the default does on their machine:
- Only the services that mount that volume are stopped, not the whole project.
- Every cold volume in one backup shares a single stop-and-start, so a project with four undeclared volumes has one downtime window, not four.
- The services come back up even if the copy fails.
- An operator can run
morzer backup --no-downtime, which skips undeclared volumes rather than copying them live. Their nightly backup then quietly covers less than it looks like it does — which is the outcome your declarations exist to prevent.
That last point is the argument for declaring. A vendor who classifies their volumes gives operators a fast backup that covers everything; a vendor who declares nothing forces them to choose between downtime and coverage.
Bind mounts¶
The manager never captures a bind mount, and there is no declaration that changes it. A bind mount points at an arbitrary host path — it can be enormous, it can be shared, it can be outside anything the manager manages.
If your product's data lives on a bind mount, it is not in any backup. Use a named volume.
Checking it¶
morzer release verify rejects a consistency that is not one of the three
values, so a typo fails at your terminal rather than turning into a volume
captured differently than you meant.
morzer doctor on a deployment running your release reports what is and is not
covered:
backup ! 2 of 3 named volume(s) captured — pgdata excluded by the release
See also backups for the operator's side of this, and hooks for the half of the backup that stays yours.