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
| Goal | Recommended setting | Trade-off |
|---|---|---|
| Lower CPU usage for all Restic operations | Set GOMAXPROCS=1 or GOMAXPROCS=2 on the Zerobyte container | Backups, restores, and checks may take longer |
| Lower CPU usage for one repository | Set repository compression mode to off | Uses more storage and may upload more data |
| Reduce source disk pressure | Add --read-concurrency 1 to the backup schedule | Lower throughput on fast storage |
| Improve throughput on fast storage | Try --read-concurrency 4 or --read-concurrency 8 | More source I/O and CPU pressure |
| Avoid saturating the network | Set repository upload/download limits | Longer backup or restore runtime |
| Avoid backing up very large files | Add --exclude-larger-than 10G to the backup schedule | Files 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.
| Scope | Setting | Use it for |
|---|---|---|
| Zerobyte container | GOMAXPROCS | Capping CPU available to all Restic operations: backups, restores, checks |
| Repository settings | Compression mode, upload limit, download limit | Repository-wide storage, CPU, and network trade-offs |
| Backup schedule | Advanced > Custom restic parameters | Per-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-scanExample faster schedule for a local NVMe source:
--read-concurrency 8Limit 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=2Then restart Zerobyte:
docker compose up -dUse these starting points:
| Host | Suggested value |
|---|---|
| Small NAS or low-power mini PC | 1 |
| Shared home server | 2 |
| Dedicated backup box | Leave 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.
| Mode | When to use it | Trade-off |
|---|---|---|
off | CPU is the bottleneck, data is already compressed, or storage is cheap | Larger repositories and more upload traffic |
auto | General-purpose default | Balanced CPU and storage usage |
max | Storage or upload bandwidth is expensive and backup runtime is less important | Highest 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:
| Situation | Try |
|---|---|
| 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 64Do 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 type | Suggested value |
|---|---|
| USB HDD, SD card, low-power NAS | 1 |
| Network mount or FUSE source | 1 or 2 |
| SATA SSD | 2 or 4 |
| NVMe SSD | 4 or 8 |
Use low values when the machine is CPU or disk constrained:
--read-concurrency 1Use higher values only when the source can keep up:
--read-concurrency 4If 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:
| Flag | What it does | Why it can hurt performance |
|---|---|---|
--no-cache | Disables Restic's local metadata cache | Forces Restic to fetch metadata from the repository again |
--cleanup-cache | Removes old cache directories | Can 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-scanThis 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:
- Set
GOMAXPROCS=1orGOMAXPROCS=2on the Zerobyte container. - Use repository compression mode
autofor mixed data, orofffor mostly compressed media. - Add
--read-concurrency 1to heavy backup schedules. - Keep the Restic cache on local storage.
- If the repository creates too many small objects or files, test
--pack-size 32on one schedule.
For S3-compatible storage, rclone remotes, and other object stores where each uploaded object has overhead:
- Keep compression at
autounless CPU is clearly the bottleneck. - Test
--pack-size 64on one backup schedule. - If object count is still a problem and uploads are reliable, test
--pack-size 128. - Use repository upload/download limits if the link is shared with other services.
- Avoid
--no-cache; metadata round trips are often the slow part on remote repositories.
Troubleshooting
For high CPU usage, use this order:
- Check whether compression mode is
max. If yes, switch toautooroffand run the next backup. - Set
GOMAXPROCS=2on the Zerobyte container and restart. - If the source disk is also busy, add
--read-concurrency 1to the affected backup schedule. - If the repository is remote and uploads saturate the host, add a repository upload limit.
- 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:
- Make sure the source and repository are not on the same slow disk.
- Use compression mode
autobefore tryingmax. - If the source is fast SSD/NVMe storage, try
--read-concurrency 4. - If the bottleneck is network upload, keep compression enabled and remove upload limits during a test window.
- 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.
