Skip to main content

Performance and Resource Tuning

Syncthing's resource usage scales with file count, file churn rate, and the number of peers. On a shared VPS or NAS with limited resources, unconstrained Syncthing can starve other services. Tuning ensures reliable sync without disrupting the host.

Learning Focus

Profile first, tune second. Start with systemctl status and journalctl to identify what is actually consuming resources before applying any limits.

Tool Snapshot
ResourceTuning LeverDefault
CPUSystemd CPUQuota, GOMAXPROCSUnlimited
MemorySystemd MemoryMax, folder rescan intervalsUnlimited
BandwidthmaxSendKbps / maxRecvKbps per device or globallyUnlimited
I/ORescan interval, hash concurrency, inotify limitsPeriodic rescan
File watchersinotify.max_user_watches kernel limitDepends on OS

Profiling Current Usage

profile-usage.sh
# Memory and CPU used by Syncthing
systemctl --user show syncthing --property=MemoryCurrent,CPUUsageNSec
# or
ps -o pid,rss,%cpu,comm -p $(pgrep syncthing)

# I/O activity
sudo iotop -p $(pgrep syncthing)

# Active goroutines and memory from API
STKEY="your-api-key"
CERT="$HOME/.local/share/syncthing/https-cert.pem"
curl -fs -H "X-API-Key: $STKEY" https://localhost:8384/rest/system/status \
--cacert "$CERT" | jq '{goroutines:.goroutines, alloc:.alloc, sys:.sys}'

Bandwidth Throttling

The most common tuning need — prevent Syncthing from saturating a shared uplink:

config.xml — global bandwidth limits
<options>
<!-- Global limits in KB/s (0 = unlimited) -->
<maxSendKbps>10240</maxSendKbps> <!-- 10 MB/s upload -->
<maxRecvKbps>10240</maxRecvKbps> <!-- 10 MB/s download -->
</options>

Per-device limits (overrides global for a specific peer):

config.xml — per-device limits
<device id="SLOW-PEER-ID" name="home-nas">
<maxSendKbps>1024</maxSendKbps> <!-- 1 MB/s to this peer -->
<maxRecvKbps>2048</maxRecvKbps> <!-- 2 MB/s from this peer -->
</device>

Rescan Interval Tuning

Syncthing watches files with inotify (Linux) and falls back to polling every rescan interval. Large folders with millions of files can spike CPU during rescan.

config.xml — increase rescan interval
<folder id="large-archive" path="/mnt/archive" type="sendreceive">
<!-- Default: 3600 (1 hour). Increase for rarely-changed large folders -->
<rescanIntervalS>86400</rescanIntervalS> <!-- Rescan once per day -->
<!-- Disable file watcher and rely only on periodic rescan -->
<fsWatcherEnabled>false</fsWatcherEnabled>
</folder>

Inotify Watcher Limit

Syncthing uses one inotify watch per directory. On folders with many subdirectories you may hit the kernel limit:

fix-inotify-limit.sh
# Check current limit
cat /proc/sys/fs/inotify/max_user_watches

# Temporary increase
sudo sysctl -w fs.inotify.max_user_watches=524288

# Permanent increase
echo "fs.inotify.max_user_watches=524288" | sudo tee /etc/sysctl.d/99-syncthing.conf
sudo sysctl -p /etc/sysctl.d/99-syncthing.conf

# Verify Syncthing log no longer shows inotify limit errors
journalctl --user -u syncthing | grep -i inotify

CPU Limiting with Systemd

override — CPU and memory cap
# systemctl --user edit syncthing
[Service]
CPUQuota=30%
MemoryMax=256M
MemorySwapMax=0
systemctl --user daemon-reload
systemctl --user restart syncthing

GOMAXPROCS — Limit Go Runtime Threads

override — limit goroutine parallelism
[Service]
Environment=GOMAXPROCS=2

This caps the Syncthing Go runtime to 2 OS threads, significantly reducing CPU burst on multi-core servers.

Hash Concurrency and Block Size

For very large files (multi-GB), tuning the hash concurrency reduces CPU spike during initial sync:

config.xml — hash concurrency
<options>
<!-- Number of concurrent file hashing goroutines (default: 0 = auto) -->
<hashers>2</hashers>
</options>

Performance Tuning Matrix

EnvironmentKey Tunings
Shared VPS (2 vCPU, 2 GB RAM)CPUQuota=30%, MemoryMax=512M, GOMAXPROCS=1, global bandwidth cap
NAS / high-file-count archiveIncrease rescanIntervalS, disable fsWatcherEnabled, increase inotify limit
Low-power device (Pi, IoT)GOMAXPROCS=1, maxSendKbps=512, hashers=1
High-speed LAN transferNo CPU/BW limits, increase hashers for faster initial hash
Mobile / metered connectionPer-device maxSendKbps=256, increase rescanIntervalS

Common Mistakes

MistakeSymptomFix
No bandwidth limit on a production serverOther services starved during large syncSet maxSendKbps / maxRecvKbps to 50% of line speed
Default rescan on a folder with 500k filesCPU spikes every hourIncrease rescanIntervalS to 86400+
Inotify limit hit silentlyFile changes not detected in real time — falls back to pollingIncrease max_user_watches in sysctl
No memory cap on a 1 GB VPSOOM kills Syncthing during large syncSet MemoryMax=512M in systemd override

What's Next