TCP Fast Open (TFO) is one of the simplest latency optimizations available for a VPS: a single sysctl parameter and an nginx directive can eliminate one full round trip from every repeat TCP connection. This guide covers the TFO protocol mechanics, server and client configuration, verification with kernel counters, and a benchmark methodology to measure the real-world impact. We also cover the edge cases where TFO does not help and how to pair it with other TCP optimizations for maximum effect.
How TCP Fast Open Works
A standard TCP connection requires a three-way handshake (SYN, SYN-ACK, ACK) before any application data can be sent. TFO modifies this by allowing the client to include data in the initial SYN packet, provided the client possesses a valid TFO cookie obtained from a previous connection. This collapses the handshake to zero extra round trips for repeat connections.
The TFO cookie is a cryptographic token generated by the server and sent to the client during the first connection. The client stores the cookie and presents it in subsequent SYN packets. The server validates the cookie and, if valid, processes the data immediately without waiting for the ACK to complete the handshake. This mechanism is defined in RFC 7413 and has been part of the Linux kernel since version 3.7.
Round-Trip Savings by Scenario
| Scenario | Without TFO | With TFO | Savings |
|---|---|---|---|
| First visit (no cookie) | 2 RTT (TCP + TLS) | 2 RTT (cookie is learned) | 0 RTT |
| Repeat visit (HTTP) | 1 RTT | 0 RTT | 1 RTT |
| Repeat visit (HTTPS) | 2 RTT (TCP + TLS) | 1 RTT (TLS only) | 1 RTT |
| Keep-alive reuse | 0 RTT | 0 RTT | 0 RTT |
The savings are most impactful for connection-heavy clients: mobile apps that re-establish connections frequently, API consumers making short-lived requests, and scraping or automation tools that open many connections in sequence. For browsers that use HTTP/2 or HTTP/3 multiplexing over a single connection, the benefit is smaller because fewer connections are opened in the first place.
Server-Side Configuration
Kernel Parameter
The net.ipv4.tcp_fastopen sysctl accepts a bitmask:
- 0: Disabled (default on some distributions)
- 1: Enable TFO for client (outgoing) connections
- 2: Enable TFO for server (incoming) connections
- 3: Enable both client and server roles
For a web server, set value 3 to enable both roles. The server role is what allows incoming repeat connections to skip the handshake; the client role is useful if your VPS itself makes outbound connections (e.g., to upstream APIs or databases):
# Enable TFO for both client and server
echo "net.ipv4.tcp_fastopen = 3" | sudo tee /etc/sysctl.d/99-tcp-fastopen.conf
sudo sysctl --system
# Verify
sysctl net.ipv4.tcp_fastopen
# Expected: net.ipv4.tcp_fastopen = 3
Nginx Configuration
Nginx exposes TFO as a fastopen parameter on the listen directive. The numeric value is the pending-SYN queue size for TFO connections:
server {
listen 443 ssl http2 fastopen=256;
listen 80 fastopen=256;
server_name example.com;
# ... rest of configuration
}
The queue size should be proportional to the number of concurrent connections your server handles. For a low-traffic VPS, a value of 256 is sufficient. For high-traffic servers, values up to 1024 are reasonable. The queue only stores TFO connections that arrive before the three-way handshake completes, so it does not need to match the full connection backlog.
Apache Configuration
Apache supports TFO through the mod_http2 module and the AcceptFilter directive. Enable TFO by adding the TCP_FASTOPEN socket option:
# In /etc/apache2/apache2.conf or a vhost file
AcceptFilter https TCP_FASTOPEN
AcceptFilter http TCP_FASTOPEN
Restart Apache after modifying the configuration: sudo systemctl restart apache2.
Client-Side Configuration
TFO requires both client and server support. On the client side:
- Linux clients: Set
net.ipv4.tcp_fastopen = 3(same sysctl). Most modern distributions enable this by default for the client role. - curl: Use the
--tcp-fastopenflag. Older versions may require compilation with--enable-tcp-fastopen. - Firefox: TFO is enabled by default in recent versions. Check
about:configfornetwork.tcp.tcp_fastopen_enabled. - Chromium/Chrome: Enable via
chrome://flags/#enable-tcp-fast-openor the command-line flag--enable-tcp-fast-open. - macOS: TFO is enabled by default since macOS 10.11.
- Windows: TFO is enabled by default since Windows 10 (build 1607) and Windows Server 2016.
Verification with Kernel Counters
Do not trust the configuration alone — verify with kernel counters. The nstat tool exposes TFO-specific statistics:
# Watch TFO counters in real time
watch -n 2 'nstat -az | grep -i fastopen'
# Output example:
# TcpExtTCPFastOpenPassive 1342 0.0
# TcpExtTCPFastOpenActive 0 0.0
# TcpExtTCPFastOpenFail 0 0.0
# TcpExtTCPFastOpenListenOverflow 0 0.0
| Counter | Meaning | Expected Value |
|---|---|---|
| TCPFastOpenPassive | Inbound TFO connections accepted (server role) | Increases with traffic |
| TCPFastOpenActive | Outbound TFO connections (client role) | Increases if client role is enabled |
| TCPFastOpenFail | Cookie rejected or handshake failed | Should be near zero |
| TCPFastOpenListenOverflow | TFO dropped because accept queue was full | Should be near zero; increase fastopen queue size if growing |
Generate test traffic and verify the counters increment:
# Reset counters
nstat -rs
# Generate TFO traffic from a client that supports it
curl --tcp-fastopen https://example.com/
# Check counters
nstat -az | grep FastOpen
Benchmarking TFO: Measuring the Real Impact
Use curl’s timing output to measure the difference TFO makes on a per-connection basis:
#!/bin/bash
# tfo-benchmark.sh - Compare with and without TFO
URL="https://example.com/"
echo "=== Without TFO ==="
for i in $(seq 1 10); do
curl -s -o /dev/null -w "Request $i: %{time_total}s\n" "$URL"
done
echo ""
echo "=== With TFO ==="
for i in $(seq 1 10); do
curl --tcp-fastopen -s -o /dev/null -w "Request $i: %{time_total}s\n" "$URL"
done
The first request in each series will be similar (no cookie yet for the TFO run). Starting from the second request, the TFO series should show a measurable reduction in time_total. On a VPS with 50 ms RTT to the client, expect a 40–50 ms reduction per request for repeat connections.
Pairing TFO with Other TCP Optimizations
TFO addresses latency for new connections, but it does not affect throughput, congestion control, or connection persistence. Pair it with these complementary optimizations:
- BBR congestion control: BBR does not rely on packet loss as a congestion signal, making it ideal for virtualized environments. Combined with TFO, you get both lower latency for new connections and better throughput for established ones.
- TCP window scaling: Increases the maximum TCP receive window beyond 64 KB, improving throughput on high-latency links. Required for any connection where the bandwidth-delay product exceeds 64 KB.
- HTTP/2 or HTTP/3: Multiplexing reduces the number of connections needed, which reduces the opportunities for TFO savings. However, TFO still helps when connections are first established or when connections are reset.
Caveats and Limitations
- Middlebox interference: Some firewalls and NAT gateways drop SYN packets that carry data. The kernel detects this and retries without TFO, so the failure mode is a single slow first attempt. The
TCPFastOpenFailcounter will show these failures. - First visits unchanged: TFO only benefits repeat connections. If your traffic is dominated by first-time visitors (e.g., a content site with low returning user rate), the benefit is minimal.
- No throughput benefit: TFO removes a round trip; it does not change the throughput of established connections. Use it alongside congestion control and buffer tuning for the full performance picture.
- Cookie lifetime: TFO cookies are valid for the lifetime of the server’s connection tracking table entry. On a VPS with high connection turnover, cookies may expire before the client returns, negating the benefit.
When to Skip TFO
TFO is not beneficial in every scenario. Skip it if:
- Your traffic is dominated by long-lived keep-alive connections (HTTP/2 multiplexing, WebSockets, database connections).
- Your VPS is behind a load balancer that strips or modifies TCP options. Some cloud load balancers do not pass TFO cookies through.
- Your application is I/O-bound rather than latency-bound. TFO saves milliseconds; if your application spends 500 ms on database queries, the TFO savings are negligible.
- You are running an older kernel (pre-3.7) that does not support TFO.
TCP Fast Open is a single sysctl away from measurable latency savings on repeat connections. When choosing a VPS provider for latency-sensitive applications, compare VPS providers on our comparison table to check which ones offer the network infrastructure that makes these optimizations worthwhile. Combine TFO with BBR congestion control and proper TCP buffer tuning, and you can eliminate two round trips from every repeat HTTPS connection — a meaningful improvement for any latency-sensitive workload.

Leave a Reply
You must be logged in to post a comment.