Incremental & deduplicated backups
Pro feature. Incremental/deduplicated backups require Backup Manager Pro. The free core can list snapshots but refuses to create, restore or verify them.
Every ordinary backup is a full, self-contained archive. Incremental backups instead store a snapshot whose file contents live in a shared, content-addressed blob pool — so only content that changed since the previous snapshot is uploaded, and content that repeats across backups is stored once.
This is ideal for a frequent cadence (hourly/daily) where storage and time matter. Full archives remain the reliable, standalone anchors; incrementals complement them, they don't replace them.
Mode is independent of scope. A profile's
type(full/database/files) says what to back up; itsmode(archive/incremental) says how to store it. Any scope can use either mode.
Enabling it
Set mode on a profile:
1'profiles' => [ 2 'hourly' => [ 3 'name' => env('APP_NAME'), 4 'type' => 'files', 5 'mode' => 'incremental', // ← store as a deduplicated snapshot 6 'files' => ['include' => [base_path()]], 7 'destinations' => ['s3'], 8 'path' => 'backups', 9 ],10],
Then run it like any other profile:
1php artisan backup:run --profile=hourly
The command reports how much was deduplicated:
1Snapshot app-2026-07-19-020000-1a2b3c.manifest.json2Mode Incremental snapshot3Files 12,4814Deduplicated 37 new, 12,444 reused (18.2 MB new content)5Destinations s3
How it works
1{path}/2 snapshots/3 {name}.manifest.json one index per snapshot (lists every file + its hash)4 blobs/5 {algorithm}/{ab}/{digest} the content-addressed pool (one blob per unique content)
- Every file is stored as a blob keyed by the hash of its content. Identical content — across files, snapshots, or runs — is stored exactly once.
- A snapshot's manifest is its index: it lists every file with the hash that locates its blob. Because addressing is by content, each snapshot is self-sufficient given the pool — there is no fragile chain of increments to walk on restore.
- Archive backups and snapshots coexist under the same
pathwithout collision.
Restore
Restore is identical to archive backups — the snapshot is reassembled from the pool transparently:
1php artisan backup:restore --profile=hourly # newest snapshot2php artisan backup:restore app-2026-07-19-...manifest.json --profile=hourly
Restoring an older snapshot faithfully returns its historical content, even
after newer snapshots exist, because each blob is addressed by content. All
restore options apply: --database, --files, --only=, --unsafe,
--no-verify. Verified restores check the snapshot's file-index anchor and every
blob's checksum. See Restore.
Compression & encryption
Blobs honour the profile's compression and encryption settings: each blob is
compressed and then encrypted, but still keyed by its plaintext hash, so
deduplication is fully preserved and the bytes at rest are protected.
Treat the algorithm and key as fixed for a pool's lifetime, like a repository password. Changing them leaves earlier blobs unreadable by later snapshots that expect the new setting.
Retention & garbage collection
backup:clean prunes snapshots by the same policy as archives (GFS / simple +
age / size caps), then reclaims the pool by reference-counted mark-and-sweep:
1php artisan backup:clean --profile=hourly --dry-run
1s3 would delete 3 backup(s)2 app-2026-07-12-... 2026-07-12 02:003 app-2026-07-13-... 2026-07-13 02:004 app-2026-07-14-... 2026-07-14 02:005 blob pool would reclaim 214 blob(s) · 1.9 GB
A blob is deleted only when no surviving snapshot references it — pruning one snapshot never breaks another that shares content. The sweep is fail-closed: if any surviving manifest cannot be read, no blob is deleted. See Retention.
Run
backup:cleanwhen backups are not running. Like all mark-and-sweep collectors, it assumes a stable set of snapshots for the duration of the sweep.
Verify & monitor
backup:verifyconfirms a snapshot's file index, that every referenced blob is present, and that each blob (decrypted/decompressed) hashes to its recorded value — a real restorability check.backup:listandbackup:monitorcount snapshots alongside archives, so a snapshot-only profile is never reported as empty. See CLI reference.
When to use which
| Use case | Recommended |
|---|---|
| Nightly full, kept for months | archive (self-contained anchor) |
| Hourly/daily, storage-sensitive | incremental |
| Pre-deploy rollback point | small archive, database-only |
| Many near-identical hosts/backups | incremental (cross-backup dedup) |