Restic repository health: what integrity checks prove—and what they do not
Learn what restic repository checks, full data reads, subset reads, and restore tests prove, plus a safe workflow for checking and responding to errors.

Use restic checks as evidence, not a recovery guarantee
Run a regular restic check, periodically read stored pack data, and separately rehearse restores. That is the fastest safe path to useful repository-health evidence. A clean check can show that the repository data it examined is coherent; it cannot show that you backed up the right paths, captured a database consistently, retained the needed point in time, or can rebuild the application.
This distinction matters because new backups can complete while an older pack file is damaged, a new uploads directory is outside the backup scope, or the only person with the recovery credentials has left. A snapshot list and a successful upload are useful signals, but neither is proof of recovery.
Treat repository health as several separate questions: Is repository structure consistent? Can the storage backend return pack data intact? Is the intended source data present? Can a team restore and operate the service? Record evidence for each question rather than reducing all of them to one green status.
- **Routine default:** run structural checks on a schedule and after unusual storage or maintenance events.
- **Higher assurance:** schedule rotating subset reads or periodic full data reads when repository size, bandwidth, and object-storage costs allow.
- **Recovery proof:** restore a meaningful snapshot into an isolated target and perform application-specific smoke tests.
What the normal repository check establishes
The normal restic check validates the repository’s structural consistency. It loads repository metadata and checks the relationships among indexes, packs, snapshots, trees, and blobs. It can identify missing objects, inconsistent indexes, and other conditions that prevent restic from seeing a coherent repository.
This is valuable maintenance evidence and is generally much lighter than reading every stored pack byte from the backend. Use it routinely, particularly after storage migrations, credential changes, unexplained backend errors, or interrupted maintenance. Keep the command output, repository identity, restic version, and completion time with your operational records.
However, the standard check is not a full media read. An object can still exist and be referenced correctly while its stored contents have not been read during that pass. Restic documents data-reading options separately because reading pack contents provides different evidence and has different costs.
- A clean structural check supports the claim: “The repository metadata and references were consistent at this time.”
- It does not support the claim: “Every stored pack was readable,” “our backup scope is complete,” or “the application can be recovered.”
- A failed check is actionable: preserve its output and investigate before allowing destructive maintenance such as retention pruning.
Run and record a structural check safely
Run checks from a controlled administration host or backup host that can reach the repository and has the required repository and storage credentials. Avoid placing passwords directly in shell history, command lines, source control, or terminal recordings. Use your approved secret-delivery method, restricted environment file, credential helper, or interactive prompt.
The following is an illustrative command. Adapt repository configuration and credential handling for your environment, test it against a non-production repository where possible, and do not copy placeholder values containing real secrets into scripts.
bash
# Prerequisites: restic installed; repository and storage credentials supplied
# through your approved secret mechanism; network access to the repository.
# Safe context: read-only repository validation; do not run concurrent repair or
# pruning commands while investigating an existing failure.
export RESTIC_REPOSITORY='s3:s3.amazonaws.com/example-backup-bucket/server-a'
# Supply RESTIC_PASSWORD through a protected secret mechanism, not shell history.
restic check
On success, restic should finish with output indicating that no errors were found. Treat a non-zero exit status, messages about missing packs or index errors, authentication failures, timeouts, or backend rate-limit errors as a failed or incomplete check—not as a clean result. Save the complete output outside the repository itself so it remains available during an incident.
- Capture the repository location or identifier, without publishing sensitive credentials.
- Capture start and finish times, restic version, exit status, and the operator or automation run ID.
- Alert on checks that fail and on checks that do not run by their expected deadline; monitoring only command failures misses jobs that never started.
What a full data read adds
A data-reading check asks restic to download and verify stored pack data. A full run with restic check --read-data reads all pack files in the repository. This gives stronger evidence that the backend can return stored data and that restic’s integrity validation succeeds for that data.
Use a full data read when repository damage is suspected, after a significant storage incident, before retiring an older backup tier, or as a planned deeper verification event for a repository whose recovery importance justifies the cost. It complements, but does not replace, an isolated restore test.
The cost can be substantial: the check may take a long time, consume download bandwidth, create object-storage request or retrieval charges, and compete with backups or restores. Check your storage provider’s billing, throughput limits, and lifecycle rules. Schedule the operation deliberately instead of adding it blindly to every nightly backup.
bash
# Illustrative full repository data read.
# Prerequisites: the same protected repository configuration as the structural check,
# enough time and bandwidth, and approval for applicable storage read/request charges.
# Safe context: read-only validation. Prefer a maintenance window for large repositories.
# Expected result: restic completes with no errors and exits 0.
restic check --read-data
- Record a full read as clean only when the command reaches completion with a successful exit status.
- A timeout, interrupted network connection, expired credential, or cancelled job leaves some data unverified; record the run as incomplete.
- Do not infer that a data read proves every snapshot is operationally useful. It validates stored repository data, not application startup, permissions, external services, or business correctness.
Use subset reads when full reads are too costly
For large repositories, restic check --read-data-subset can read only part of the stored data. This is a practical middle ground when a complete read would be too expensive or disruptive for every maintenance cycle. For example, a percentage is useful as a sample; a fraction can be used as part of a deliberately tracked rotation.
The critical distinction is coverage. Repeated random samples may read some data more than once while never reading other data. If your policy requires every stored pack to be read over a period, use a documented deterministic sequence supported by your restic version, or periodically run a full --read-data check. Confirm the current option behavior in the [restic repository documentation](https://restic.readthedocs.io/en/stable/045_working_with_repos.html) before automating a coverage claim.
bash
# Illustrative sampling command only. Verify option syntax and semantics against the
# installed restic version before scheduling it. This sample does NOT prove full coverage.
# Prerequisites and credential handling are the same as for restic check.
restic check --read-data-subset=5%
Choose cadence from repository size, change rate, backend reliability signals, recovery importance, and cost. A small but critical repository may justify frequent complete reads. A large archive may need routine structural checks, rotating data reads, and a less frequent full read. Document the decision so an operator knows exactly what “verified” means.
- Label a percentage run as “sampled data read,” not “full integrity verification.”
- Track planned versus completed runs, including skipped schedules and failed attempts.
- Run an additional structural check after an incomplete or failed data-read job, but do not let that lighter result erase the incomplete data-read record.
Integrity checks cannot tell you whether you protected the right data
Restic can validate what is in the repository; it cannot determine what should have been backed up. A repository can be internally perfect while a deployment moved persistent data to a new Docker volume, a bind mount was omitted, a database export selected the wrong database, or an uploads directory was never included.
This is especially important for containers. A Compose file can recreate containers, but named volumes, bind-mounted application data, database artifacts, environment and secret-recovery procedures, and external dependencies each need an explicit recovery method. Review [how Docker volume and mount coverage drifts](/blog/detect-docker-volume-mount-backup-coverage-drift) whenever the service changes.
Repository integrity also cannot establish application consistency. For example, copying a live database data directory using an unsupported method may produce bytes that are stored and read perfectly but cannot be used as a valid database recovery. Use database-native logical or physical backup methods appropriate to the engine, then back up the resulting artifacts.
- Maintain a recovery map covering application data, database data or exports, uploads, configuration, certificates, service definitions, and necessary recovery credentials.
- Compare current paths, mounts, and database inventory to the backup definition after deployments and configuration changes.
- Inspect a restored copy for recent, recognizable data—not merely for the existence of files.
Technical basis
First-party references
Technical claims and limitations in this guide were checked against these primary sources. Confirm version-specific behavior when designing a production recovery process.
Related from Rested
Common questions
Frequently asked questions
What does the default restic check verify?
The standard restic check validates repository structure and consistency, including indexes and the relationships among packs, snapshots, trees, and blobs. It does not read every stored pack byte unless a data-reading option is used.
Does `restic check --read-data` download the entire repository?
It reads all repository pack data from the configured backend. Depending on repository size and storage design, that can require substantial time, bandwidth, object-storage requests, and retrieval charges.
Is a random subset check eventually guaranteed to cover every stored pack?
No. Sampling can select some data repeatedly while other data remains unread. If complete coverage is required, use a documented tracked rotation supported by your restic version or schedule a full data read.
Can a restic repository check prove that my database backup is valid?
No. It can provide evidence about the integrity of repository data it examines. It cannot prove that the database was captured consistently, that required roles or extensions are present, or that a restored database starts and contains the expected application state.
What should I do if restic check reports repository damage?
Preserve the complete output, stop destructive maintenance such as forget and prune, and assess whether you can make a separate copy of the repository before attempting repair. Investigate the storage cause as well as the repository symptom, follow current official troubleshooting guidance for your exact restic version, and validate recovery after any repair.