Last updated: March 15, 2026

Optimize WireGuard throughput for large file transfers by tuning MTU to 1400-1450 bytes to avoid fragmentation from WireGuard’s UDP overhead, increasing kernel buffer sizes (net.core.rmem_max, net.core.wmem_max to 256MB+), and enabling TSO/GSO (TCP Segmentation Offload) for hardware acceleration of ChaCha20-Poly1305 encryption. Monitor actual throughput with iperf3 through the tunnel to identify bottlenecks, and configure TCP_NODELAY on application sockets to prevent buffering delays. WireGuard’s modern cryptography and improved design provide excellent throughput, but default kernel settings assume interactive traffic, bulk transfers require explicit tuning to reach gigabit speeds.

Table of Contents

Understanding WireGuard Performance Characteristics

WireGuard uses modern cryptographic primitives and an improved codebase, typically achieving throughput that exceeds older VPN protocols. However, several factors can limit performance:

MTU Configuration for Large Transfers

One of the most impactful optimizations involves proper MTU tuning. WireGuard operates at the IP layer, encapsulating packets within UDP. This adds overhead that can cause fragmentation if not properly accounted for.

Calculating Optimal MTU

The standard Ethernet MTU is 1500 bytes. WireGuard adds its own overhead:

For a typical configuration, setting MTU to 1420 provides a safe margin:

/etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
MTU = 1420
PrivateKey = <server-private-key>

[Peer]
PublicKey = <client-public-key>
AllowedIPs = 10.0.0.2/32
PersistentKeepalive = 25

For paths with known lower MTU networks (such as tunneled connections), reduce further:

For paths through additional VPN tunnels or satellite links
MTU = 1280

Test your MTU with ping tests using the Don’t Fragment flag:

Test maximum unfragmented packet size
ping -M do -s 1400 -c 3 10.0.0.2

Kernel Parameter Tuning

Linux kernel parameters significantly impact WireGuard throughput. Apply these settings in /etc/sysctl.conf or via sysctl commands:

Network Buffer Sizes

Increase network buffer sizes
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 4194304
net.core.wmem_default = 4194304
net.core.netdev_max_backlog = 50000
net.core.optmem_max = 25165824

TCP Window Scaling

Enable TCP window scaling for improved throughput
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

Apply Changes

Apply without reboot
sudo sysctl -p

Verify current values
sysctl net.core.rmem_max

WireGuard-Specific Performance Options

Inline Configuration for Reduced Overhead

While not strictly a performance feature, keeping configuration inline eliminates additional file I/O:

Single full configuration file
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <key>
MTU = 1420
SaveConfig = false

[Peer]
Multiple peers for redundancy
PublicKey = <peer1-key>
AllowedIPs = 10.0.0.2/32, 192.168.100.0/24
Endpoint = peer1.example.com:51820
PersistentKeepalive = 25

[Peer]
PublicKey = <peer2-key>
AllowedIPs = 10.0.0.3/32
Endpoint = peer2.example.com:51820

PersistentKeepalive Considerations

For large file transfers, the PersistentKeepalive setting affects NAT/firewall state maintenance:

Recommended for NATed environments
PersistentKeepalive = 25

Can be disabled for server-to-server with static IPs
PersistentKeepalive = 0

CPU and Encryption Optimization

WireGuard encryption performance varies across CPU architectures. Modern processors with AES-NI or ARM cryptographic extensions provide hardware acceleration benefits, though ChaCha20-Poly1305 is designed to be efficient on all platforms.

Multi-Core Utilization

WireGuard runs in kernel space (with the wireguard module) and benefits from multi-core systems. Ensure your system uses the kernel module rather than the userspace implementation:

Check if kernel module is loaded
lsmod | grep wireguard

Load module if needed
sudo modprobe wireguard

Verify kernel module is active
sudo wg show

CPU Frequency Scaling

For consistent performance, disable CPU frequency scaling during bulk transfers:

Set CPU to performance mode
sudo cpupower frequency-set -g performance

Or use the kernel command line for always-on performance
Add - processor.max_cstates=1

Network Path Optimization

Using Alternate Ports

Some networks throttle WireGuard’s default UDP port 51820. Consider alternate ports:

Using non-standard port
ListenPort = 51821

Or common alternative ports
ListenPort = 443 # May work behind restrictive firewalls

Bonding Multiple Connections

For maximum throughput between two points, consider link bonding with LACP or similar:

Create bonded interface
sudo ip link add bond0 type bond mode 802.3ad
sudo ip link set eth0 master bond0
sudo ip link set eth1 master bond0

Run WireGuard over bonded link

Benchmarking Your Setup

After applying optimizations, verify improvements with standardized tests:

iperf3 Testing

Server side
iperf3 -s -p 5201

Client side
iperf3 -c 10.0.0.1 -p 5201 -t 30 -i 1

File Transfer Testing

Using scp or rsync over WireGuard
time rsync -avz --progress /large/file/path 10.0.0.2:/destination/

Using netcat for raw throughput
nc -l -p 9000 > /dev/null &
nc 10.0.0.2 9000 < /dev/zero | pv -r > /dev/null

Practical Deployment Example

A production-ready configuration for file transfer servers:

Server configuration (wg0.conf)
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <server-private-key>
MTU = 1420

Performance tuning via post-up/post-down
PostUp = sysctl -w net.core.rmem_max=16777216 net.core.wmem_max=16777216
PostUp = sysctl -w net.core.netdev_max_backlog=50000

[Peer]
PublicKey = <client-public-key>
AllowedIPs = 10.0.0.2/32
PersistentKeepalive = 25

Apply the same kernel tuning to both endpoints for consistent performance.

Monitoring and Maintenance

Track performance over time with monitoring:

Check current throughput
sudo wg show wg0 transfer

Monitor with iftop
sudo iftop -i wg0

Log performance metrics
sudo watch -n1 'sudo wg show wg0'

Troubleshooting Common Throughput Problems

Even after applying the standard tuning, you may still see disappointing throughput. Here are the most common culprits and how to diagnose them.

Fragmentation Causing Retransmissions

If throughput is low but CPU usage is also low, fragmentation is the likely culprit. Check with:

Look for IP fragment reassembly activity
cat /proc/net/snmp | grep -i frag

Check interface statistics for errors
ip -s link show wg0

If the ReasmOKs counter is non-zero, packets are being fragmented. Lower your MTU in 10-byte increments until fragmentation stops.

IRQ and CPU Affinity

On servers with multiple cores, network interrupts may all land on a single CPU, creating a bottleneck while other cores sit idle:

Check IRQ distribution across CPUs
cat /proc/interrupts | grep eth0

Identify which CPU handles which queue
ls /sys/class/net/eth0/queues/

Set IRQ affinity manually if needed (replace X with IRQ number)
echo 3 > /proc/irq/X/smp_affinity   # Route to CPUs 0 and 1 (bitmask)

For sustained transfers, enabling irqbalance is usually sufficient on most hardware:

sudo apt install irqbalance
sudo systemctl enable --now irqbalance

TCP Congestion Algorithm

The default Linux congestion algorithm (cubic) is designed for long-haul links with some packet loss. For local or LAN transfers through WireGuard, bbr often performs better:

Check current algorithm
sysctl net.ipv4.tcp_congestion_control

Enable BBR (requires kernel 4.9+)
echo 'net.ipv4.tcp_congestion_control = bbr' | sudo tee -a /etc/sysctl.conf
echo 'net.core.default_qdisc = fq' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Verify
sysctl net.ipv4.tcp_congestion_control

BBR improves throughput on paths with any latency because it models the bottleneck bandwidth directly rather than relying on loss signals.

WireGuard on Windows and macOS

The tuning principles are the same across platforms, but the implementation differs.

Windows

Windows WireGuard uses the official wireguard.exe or the WireGuardNT kernel driver introduced in 2021, which significantly improved throughput over the earlier WinTun implementation:

Check if WireGuardNT driver is installed (PowerShell admin)
Get-NetAdapter | Where-Object {$_.InterfaceDescription -like "*WireGuard*"}

MTU is set per interface via the config file. same INI syntax as Linux
Check actual MTU:
netsh interface ipv4 show subinterfaces

For Windows bulk transfers, also check TCP Auto-Tuning:

Verify TCP auto-tuning is enabled
netsh interface tcp show global
Should show "Receive Window Auto-Tuning Level: normal"

Enable if disabled
netsh interface tcp set global autotuninglevel=normal

macOS

macOS WireGuard uses the userspace implementation (wireguard-go). It is notably slower than the Linux kernel module. typically 50, 70% of equivalent Linux throughput on the same hardware. This is a fundamental limitation of the userspace architecture.

Install via Homebrew or the Mac App Store
brew install wireguard-tools

MTU setting via config file. same syntax
macOS does not expose sysctl knobs for rmem/wmem in the same way
Focus on correct MTU and let macOS handle the rest

If maximum throughput matters on macOS, consider running WireGuard in a Linux VM and bridging the network. this may sound counterproductive but can deliver full kernel-module performance for sustained bulk transfers.

Frequently Asked Questions

Who is this article written for?

This article is written for developers, technical professionals, and power users who want practical guidance. Whether you are evaluating options or implementing a solution, the information here focuses on real-world applicability rather than theoretical overviews.

How current is the information in this article?

We update articles regularly to reflect the latest changes. However, tools and platforms evolve quickly. Always verify specific feature availability and pricing directly on the official website before making purchasing decisions.

Does WireGuard offer a free tier?

Most major tools offer some form of free tier or trial period. Check WireGuard’s current pricing page for the latest free tier details, as these change frequently. Free tiers typically have usage limits that work for evaluation but may not be sufficient for daily professional use.

Can I trust these tools with sensitive data?

Review each tool’s privacy policy, data handling practices, and security certifications before using it with sensitive data. Look for SOC 2 compliance, encryption in transit and at rest, and clear data retention policies. Enterprise tiers often include stronger privacy guarantees.

What is the learning curve like?

Most tools discussed here can be used productively within a few hours. Mastering advanced features takes 1-2 weeks of regular use. Focus on the 20% of features that cover 80% of your needs first, then explore advanced capabilities as specific needs arise.

Related Articles