Zerobyte

Performance Tuning

Reduce CPU, network, and disk pressure from backups and restores

Most performance tuning is a trade between CPU, network bandwidth, source disk I/O, and repository storage. This guide covers the Zerobyte settings and Restic flags that are safe to adjust.

Change one setting at a time, then compare runtime, CPU, memory, network usage, source disk pressure, and repository behavior. A setting that helps one source can make another source worse.

Quick recipes

GoalRecommended settingTrade-off
Lower CPU usage for all Restic operationsSet GOMAXPROCS=1 or GOMAXPROCS=2 on the Zerobyte containerBackups, restores, and checks may take longer
Lower CPU usage for one repositorySet repository compression mode to offUses more storage and may upload more data
Reduce source disk pressureAdd --read-concurrency 1 to the backup scheduleLower throughput on fast storage
Improve throughput on fast storageTry --read-concurrency 4 or --read-concurrency 8More source I/O and CPU pressure
Avoid saturating the networkSet repository upload/download limitsLonger backup or restore runtime
Avoid backing up very large filesAdd --exclude-larger-than 10G to the backup scheduleFiles above the limit are skipped

Where to tune

Some settings apply globally, some apply to one repository, and some apply only to one backup schedule.

ScopeSettingUse it for
Zerobyte containerGOMAXPROCSCapping CPU available to all Restic operations: backups, restores, checks
Repository settingsCompression mode, upload limit, download limitRepository-wide storage, CPU, and network trade-offs
Backup scheduleAdvanced > Custom restic parametersPer-source backup behavior such as read concurrency, pack size, scan mode

Custom Restic parameters are appended to the restic backup command for that schedule only. Enter one flag per line.

Example low-impact schedule:

--read-concurrency 1
--exclude-larger-than 10G
--no-scan

Example faster schedule for a local NVMe source:

--read-concurrency 8

Limit Restic CPU usage with GOMAXPROCS

The standard Go environment variable GOMAXPROCS limits how many operating system threads can execute Go code at the same time. Add it to the Zerobyte container environment:

services:
  zerobyte:
    environment:
      - GOMAXPROCS=2

Then restart Zerobyte:

docker compose up -d

Use these starting points:

HostSuggested value
Small NAS or low-power mini PC1
Shared home server2
Dedicated backup boxLeave unset, or use 4 if you still want a cap

Choose compression mode

Repository compression mode is configured on the repository form. Zerobyte passes it to Restic backups as --compression.

ModeWhen to use itTrade-off
offCPU is the bottleneck, data is already compressed, or storage is cheapLarger repositories and more upload traffic
autoGeneral-purpose defaultBalanced CPU and storage usage
maxStorage or upload bandwidth is expensive and backup runtime is less importantHighest CPU usage

Good candidates for off include video libraries, JPEG/HEIC photo archives, already-compressed archives such as .zip, .7z, .gz, and .zst, VM images, and application data that is compressed before Zerobyte sees it.

Good candidates for max include text-heavy project directories, logs, and slow or expensive remote storage links where CPU is available.

Compression mode affects new backup data. It does not rewrite or recompress existing packs already stored in the repository.

Limit upload and download bandwidth

Repository settings include upload and download limits. These map to Restic's --limit-upload and --limit-download options and apply to operations for that repository.

Use bandwidth limits when backups make the internet connection unusable, a remote storage provider throttles or disconnects large transfers, or restores should not starve other services on the same host.

Prefer the repository bandwidth fields over custom Restic parameters. The UI uses Kbps, Mbps, and Gbps; Zerobyte converts those values to the unit Restic expects.

Tune pack size

Restic stores data in pack files. The --pack-size option changes the target pack size in MiB. Restic's default target is 16 MiB.

Larger pack files can improve performance when the bottleneck is per-file or per-object overhead rather than raw throughput. This is common with very large repositories with many pack files, backends with file count or object count pressure, Google Drive or similar rclone-backed storage, OpenStack Swift-like object storage, and local HDD repositories where creating many small files is expensive.

Suggested starting points:

SituationTry
Slow HDD or small NAS repository--pack-size 32
Large repository on object storage or rclone--pack-size 64
Very large repository with high upload speed--pack-size 128

Example:

--pack-size 64

Do not jump straight to very large values. Larger packs reduce object count, but each pack is a larger unit to upload, retry, rewrite, and cache. If an upload fails near the end of a large pack, more work may need to be repeated.

In Zerobyte, --pack-size in custom Restic parameters affects only the backup schedule where you set it. It does not rewrite existing repository data and it does not automatically apply to every other schedule.

Tune read concurrency

--read-concurrency controls how many files Restic reads in parallel during backup. It is one of the most useful knobs for slow machines because it directly changes pressure on the source filesystem.

Source typeSuggested value
USB HDD, SD card, low-power NAS1
Network mount or FUSE source1 or 2
SATA SSD2 or 4
NVMe SSD4 or 8

Use low values when the machine is CPU or disk constrained:

--read-concurrency 1

Use higher values only when the source can keep up:

--read-concurrency 4

If the backup host becomes sluggish, lower --read-concurrency before changing pack size. If Restic is idle waiting on storage, increase it one step and compare the next run.

Keep the cache local

Restic uses a local cache for repository metadata. Zerobyte places this cache in the configured Restic cache directory, which defaults to /var/lib/zerobyte/restic/cache inside the container.

Keep the cache on local storage. Do not place /var/lib/zerobyte or the Restic cache on a network share. A slow cache can make snapshots, checks, forget operations, and backups feel much slower than the repository itself.

Avoid these flags unless you are diagnosing a cache problem:

FlagWhat it doesWhy it can hurt performance
--no-cacheDisables Restic's local metadata cacheForces Restic to fetch metadata from the repository again
--cleanup-cacheRemoves old cache directoriesCan discard cache data useful to later operations

If a repository behaves strangely after moving storage or changing credentials, --cleanup-cache can be useful for one diagnostic run. Do not leave it in a normal schedule as a performance tweak.

Skip progress scanning

By default, Restic scans the source to estimate total work and provide progress information. On very large trees, slow network mounts, or filesystems with high directory traversal cost, that initial scan can be expensive.

Use --no-scan to skip the initial scan:

--no-scan

This can make a backup start doing useful work sooner, but progress reporting may be less complete. It does not reduce the actual file content Restic must read to create the backup.

Baselines

For a low-power NAS, mini PC, or shared server, start with this conservative setup:

  1. Set GOMAXPROCS=1 or GOMAXPROCS=2 on the Zerobyte container.
  2. Use repository compression mode auto for mixed data, or off for mostly compressed media.
  3. Add --read-concurrency 1 to heavy backup schedules.
  4. Keep the Restic cache on local storage.
  5. If the repository creates too many small objects or files, test --pack-size 32 on one schedule.

For S3-compatible storage, rclone remotes, and other object stores where each uploaded object has overhead:

  1. Keep compression at auto unless CPU is clearly the bottleneck.
  2. Test --pack-size 64 on one backup schedule.
  3. If object count is still a problem and uploads are reliable, test --pack-size 128.
  4. Use repository upload/download limits if the link is shared with other services.
  5. Avoid --no-cache; metadata round trips are often the slow part on remote repositories.

Troubleshooting

For high CPU usage, use this order:

  1. Check whether compression mode is max. If yes, switch to auto or off and run the next backup.
  2. Set GOMAXPROCS=2 on the Zerobyte container and restart.
  3. If the source disk is also busy, add --read-concurrency 1 to the affected backup schedule.
  4. If the repository is remote and uploads saturate the host, add a repository upload limit.
  5. Watch a few scheduled runs before making further changes.

If backups are still too heavy, reduce the schedule frequency or split very large sources into separate schedules so the heavy work does not run all at once.

For slow backups, use this order:

  1. Make sure the source and repository are not on the same slow disk.
  2. Use compression mode auto before trying max.
  3. If the source is fast SSD/NVMe storage, try --read-concurrency 4.
  4. If the bottleneck is network upload, keep compression enabled and remove upload limits during a test window.
  5. Check repository storage latency. Cloud, rclone, and network filesystems can be much slower than local disk.

A faster backup that starves the NAS, VM host, or network may be worse than a slower predictable one.