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.
Profile first, tune second. Start with systemctl status and journalctl to identify what is actually consuming resources before applying any limits.
| Resource | Tuning Lever | Default |
|---|---|---|
| CPU | Systemd CPUQuota, GOMAXPROCS | Unlimited |
| Memory | Systemd MemoryMax, folder rescan intervals | Unlimited |
| Bandwidth | maxSendKbps / maxRecvKbps per device or globally | Unlimited |
| I/O | Rescan interval, hash concurrency, inotify limits | Periodic rescan |
| File watchers | inotify.max_user_watches kernel limit | Depends on OS |
Profiling Current Usage
# 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:
<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):
<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.
<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:
# 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
# systemctl --user edit syncthing
[Service]
CPUQuota=30%
MemoryMax=256M
MemorySwapMax=0
systemctl --user daemon-reload
systemctl --user restart syncthing
GOMAXPROCS — Limit Go Runtime Threads
[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:
<options>
<!-- Number of concurrent file hashing goroutines (default: 0 = auto) -->
<hashers>2</hashers>
</options>
Performance Tuning Matrix
| Environment | Key Tunings |
|---|---|
| Shared VPS (2 vCPU, 2 GB RAM) | CPUQuota=30%, MemoryMax=512M, GOMAXPROCS=1, global bandwidth cap |
| NAS / high-file-count archive | Increase rescanIntervalS, disable fsWatcherEnabled, increase inotify limit |
| Low-power device (Pi, IoT) | GOMAXPROCS=1, maxSendKbps=512, hashers=1 |
| High-speed LAN transfer | No CPU/BW limits, increase hashers for faster initial hash |
| Mobile / metered connection | Per-device maxSendKbps=256, increase rescanIntervalS |
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| No bandwidth limit on a production server | Other services starved during large sync | Set maxSendKbps / maxRecvKbps to 50% of line speed |
| Default rescan on a folder with 500k files | CPU spikes every hour | Increase rescanIntervalS to 86400+ |
| Inotify limit hit silently | File changes not detected in real time — falls back to polling | Increase max_user_watches in sysctl |
| No memory cap on a 1 GB VPS | OOM kills Syncthing during large sync | Set MemoryMax=512M in systemd override |