1
Differential-Backups
Jonathan Miller edited this page 2026-07-13 01:04:07 +00:00

Differential Backups

A differential backup captures only the files that have changed since the most recent full backup for the same profile, instead of re-archiving the entire site. This makes routine backups smaller and faster while still allowing a restore from a full + differential pair.

Differential logic applies to the file portion of a backup only. The database is always dumped in full on every run (differential backups still contain a complete database.sql).

Enabling it

Set the profile's backup_type to differential (#__mokosuitebackup_profiles.backup_type). The other backup types are full, database, and files.

How it works

Change detection is handled by DifferentialScanner (com_mokosuitebackup/src/Engine/DifferentialScanner.php) using a stored file manifest.

1. Manifests on full backups

When a full backup runs, after scanning the filesystem BackupEngine builds a JSON manifest of every included file and stores it on the backup record (#__mokosuitebackup_records.manifest). The manifest maps each relative path to its size and modification time:

{
  "index.php":            { "size": 1234, "mtime": 1717350000 },
  "templates/site/x.css": { "size":  512, "mtime": 1717340000 }
}

2. Finding the base

When a differential backup runs, BackupEngine::loadBaseManifest() loads the manifest from the most recent full backup for that profile whose status is complete or warning and whose manifest is non-empty (newest backupstart first).

  • No base found — if there is no prior full backup with a manifest, the differential falls back to a full backup: it archives every file and builds a fresh manifest for future differentials. The log records No base full backup found — running full backup instead.

3. Comparing files

DifferentialScanner::getChangedFiles() walks the current file list from FileScanner and keeps a file when:

  • it is new (not present in the base manifest), or
  • it is modified — its current size or mtime differs from the base manifest entry.

Unchanged files (same path, size, and mtime) are skipped. Only the changed/new set is added to the archive. The log records, e.g., Differential: 37 changed files out of 12048 total.

4. Linking to the base

Differential records reference their base full backup via #__mokosuitebackup_records.base_record_id, so a restore knows which full backup to combine with the differential.

Restore model

Restoring a point-in-time differential means restoring its base full backup first, then overlaying the differential's changed files on top. Because the manifest tracks size/mtime rather than deletions, differentials capture new and modified files; the base full backup provides the complete baseline.

Configuration summary

Setting Where Effect
backup_type = differential Profile Enables differential file capture for the profile
manifest Record (_records) JSON path→size/mtime map; written on full backups, read by differentials
base_record_id Record (_records) Links a differential to the full backup it is based on

Notes & limitations

  • Change detection uses size and modification time, not content hashing — a file whose contents change without altering size or mtime would not be detected as changed. This is a deliberate performance trade-off.
  • A differential always contains a full database dump; only files are differential.
  • Keep the base full backup available: pruning it (via retention) leaves its differentials without a baseline. Plan retention so a full backup outlives the differentials that depend on it.
  • Exclusions (exclude_dirs, exclude_files) apply the same way on full and differential runs, so the compared file universe is consistent.