Guide
restic check vs borg check vs kopia verify, compared
All three tools ship a command called some variant of 'check' or 'verify.' None of them mean the same thing by default, and the difference is exactly where people get burned.
The shared trap: every one of these tools has a fast, cheap command that sounds like it proves your backup is good, and by default none of them re-read the actual data blocks to confirm the bytes are intact. They check structure, that the pieces the repository claims to have actually exist and reference each other correctly. That is real and worth running. It is not the same claim as "the data in those pieces is still correct," and the gap between those two claims is exactly where bit-rot and partial uploads hide.
What the default command actually checks
| Tool | Default command | What it verifies by default |
|---|---|---|
restic | restic check | Index and pack-file structure: every chunk a snapshot references actually exists and the index is internally consistent. Does not re-read pack contents. |
borg | borg check | Repository consistency and archive metadata consistency: that every chunk an archive references is present. Does not decrypt or checksum chunk contents. |
kopia | kopia content verify | That every content block referenced by the index actually exists in the repository. Without --full, it doesn't re-hash the block's actual bytes. |
Read that middle column again: all three, by default, are checking that the map is internally consistent, not that the territory it points to is still what it claims to be. A pack file that's had a handful of bits flip on disk will pass every one of these default commands without a complaint.
The flag that actually re-reads your data
| Tool | Deep verification | Granularity |
|---|---|---|
restic | restic check --read-data (everything) or --read-data-subset=5% (a slice) | Adjustable. You can sample a percentage per run and cover the whole repository over several runs. |
borg | borg check --verify-data | All or nothing. There's no partial option: it decrypts and CRC-checks every data block, every run. |
kopia | kopia content verify --full, plus kopia snapshot verify --verify-files-percent=N | Content verify's --full is all-or-nothing at the content layer; snapshot verify has its own separate percentage sampling at the file layer. |
restic's percentage knob is the most forgiving one to run often: --read-data-subset=5% on a nightly schedule samples the whole repository over roughly a couple of months without ever making one run painfully slow or expensive on egress. Borg's design gives you no equivalent, it's either a full re-read every time (real cost on a large repo, especially against a remote target) or you're back to structural-only checks between occasional full ones. Kopia sits in between: content verify --full is binary like Borg's, but snapshot verify's file-percent sampling gives you something closer to restic's gradual-coverage approach at the file level.
The gotcha specific to each tool
- restic: the default
restic checkwith no flags is genuinely fast and genuinely limited. It's easy to run it, see green, and assume you're covered on data integrity when you've only confirmed the index isn't lying to itself. - borg: because
--verify-datais all-or-nothing and can be slow against a large repository, the honest temptation is to just... not run it, and rely on structural checks indefinitely. That's the same trap as restic's default, just with a worse excuse, since there's no cheap partial option to fall back to. - kopia: the sharpest one, and not obvious from the docs: Kopia maintains a local metadata cache, and a warm cache can make a verify command report a repository as healthy even when the actual remote content is damaged, because it's answering from cache rather than actually reaching the backend. Any verification command you trust needs to run against a deliberately fresh cache, not whatever happens to be sitting on disk from the last run.
What this means for how often you actually run these
Structural checks are cheap enough to run on every backup. Full data verification usually isn't, which is exactly why so many setups quietly never run it at all past the first week. The practical answer isn't "always do the expensive thing," it's picking a cadence that actually gets exercised: restic's percentage subset or Kopia's file-percent sampling on every run, or Borg's full --verify-data on a slower schedule (weekly, monthly) than the plain structural check.
This is also the reason a scheduled, alerting check-in matters more than the specific command: the tool doesn't fail loudly when you stop running its own verification, it just goes back to reporting whatever the last check happened to find. Whichever of these three you're on, Vestal's agents run the tool's own deep-verify flag on a schedule and only report success when it actually passed, restic with --read-data-subset, Borg with --verify-data, Kopia against a fresh cache. See the docs for the exact setup per tool, or read the restic restore-testing walkthrough first if you haven't done this by hand yet.
Whichever of the three you run, the schedule is the part that actually fails.
One line after your existing backup job. Free to start, no card required.