Slow upload performance behind NGINX reverse proxy running on Linux
Your upload performance may have a bottleneck at the reverse proxy due to its TCP congestion control algorithm. It's easy to change.
The upload speed at my house was always crap, but my cable ISP recently gave me a big bump in upload speed. I was excited, but my upload performance stayed the same, which was a bummer. For a while I blamed my ISP for underhanded shenanigans, but I started to suspect the problem was on my end. I tried everything I could think of: NGINX proxy server configuration, router settings, tweaks to lots of things, but the problem turned out to be my Linux proxy server's TCP congestion control algorithm.
I hadn't heard of this before. Older congestion control algorithms like cubic depend on packet loss to signal congestion, so once packet loss is detected it drops the transfer speed. For me, switching to the BBR (Bottleneck Bandwidth and Round-trip propagation time) algorithm was the solution. BBR doesn't look at packet loss as a sign of congestion. Instead, it looks at total bandwidth and round-trip time to optimize transfer rate. This can be especially helpful in high latency situations since BBR waits for packets to arrive.
In certain cases, and definitely in my case, switching to BBR led to a massive improvement. I'm seeing about 10x improvement in upload performance, so now I'm actually getting the ISP's advertised upload speeds which I thought was impossible. In fact, even before my ISP's upload speed bump, I was probably significantly bottlenecked and had no idea. Ugh.
Switching your TCP algorithm to BBR
If you want to try BBR on your Linux reverse proxy, it's easy and reversible.
1. Check which TCP congestion control algorithm is active now:
sudo sysctl net.ipv4.tcp_congestion_control
2. Enable BBR:
sudo sysctl -w net.core.default_qdisc=fq
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
3. Run the first command again to see if BBR is enabled:
sudo sysctl -n net.ipv4.tcp_congestion_control
4. If you like the performance, you can make the setting persistent by editing sysctl.conf:
sudo nano /etc/sysctl.conf
(on Debian, Ubuntu)
sudo nano /etc/sysctl.d/99-sysctl.conf
(on Arch)
Add these two lines to the end of the file and save:
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
BBR will now be enabled upon boot.