How to Enable TCP Fast Open in Nginx

Enable TCP Fast Open in Nginx with net.ipv4.tcp_fastopen, listen fastopen settings, curl probes, kernel counters, and rollback.

Last updatedAuthorJoshua JamesRead time9 minGuide typeNginx

Enable TCP Fast Open in Nginx only when the listener can safely accept request data before the TCP handshake fully completes. The workflow is to enable Linux server-side TFO with net.ipv4.tcp_fastopen, add the Nginx listen ... fastopen=... parameter, then verify kernel counters instead of trusting a normal HTTP response.

Fast Open belongs on the listen directive inside a server block. Use it for repeat clients on high-latency paths, and avoid it on endpoints where replayed early data could create duplicate application actions.

Understand TCP Fast Open in Nginx

RFC 7413 defines TCP Fast Open as an experimental TCP extension that allows data in the opening SYN packet. For a web server, the practical goal is to remove one round trip from repeat connections after the client has a Fast Open cookie.

ItemTCP Fast Open value for Nginx
Nginx parameterfastopen=256 on a listen directive
Nginx directive contextserver, because fastopen is a listen socket parameter
Linux sysctlnet.ipv4.tcp_fastopen
Minimum Linux value for an Nginx listener2 enables server-side support; 3 enables client and server support
Required Nginx apply flowsudo nginx -t, then sudo systemctl reload nginx
Main cautionUse only when the listener can tolerate duplicate SYN data being processed more than once

How TCP Fast Open Changes the Handshake

A normal TCP connection completes the three-way handshake before the client sends an HTTP request:

Traditional TCP connection:
1. Client sends SYN.
2. Server replies with SYN-ACK.
3. Client sends ACK.
4. Client sends the HTTP request.
5. Server sends the HTTP response.

TCP Fast Open changes that flow on later connections. The first connection requests and stores a cookie. A later connection can place request data in the SYN packet, and the server can begin processing that data before the handshake finishes.

TCP Fast Open connection after cookie exchange:
1. Client sends SYN with a Fast Open cookie and request data.
2. Server validates the cookie and replies with SYN-ACK.
3. Server can process the early request data.
4. Client sends ACK.
5. Server sends the HTTP response.

When TCP Fast Open Helps Nginx

TFO is most useful when clients reconnect often and the network path adds noticeable latency. Static assets, cacheable GET requests, API reads, and repeat mobile clients are better candidates than rare one-off visits.

  • Good candidates: Static files, read-only API endpoints, idempotent GET and HEAD requests, and cache-heavy sites where duplicated early data will not change state.
  • Riskier candidates: Login flows, payment callbacks, form submissions, POST-heavy applications, and dynamic backends that cannot tolerate replayed request data.
  • Proxy or CDN paths: Enable and verify TFO where the visitor’s TCP connection terminates. If a load balancer or CDN terminates TCP before your origin, the origin’s TFO setting may not affect visitor latency.

The official Nginx listen documentation warns not to enable fastopen unless the server can handle the same SYN packet with data more than once. Treat that as an application-safety requirement, not a kernel-support footnote.

Enable TCP Fast Open in the Linux Kernel

Nginx can set the listening socket option, but Linux still needs server-side TCP Fast Open enabled through net.ipv4.tcp_fastopen. Check the current value first:

cat /proc/sys/net/ipv4/tcp_fastopen

Upstream Linux kernel documentation lists 1 as the default, which enables client-side support only. For an Nginx listener, 1 is not enough because server-side support is off.

1

Keep the starting value as your rollback baseline, especially on managed servers or images that set kernel networking defaults outside the upstream baseline.

Understand net.ipv4.tcp_fastopen Values

The Linux kernel IP sysctl documentation defines tcp_fastopen as a bitmask. These are the common values used for Nginx:

ValueMeaningNginx relevance
0TFO disabledNginx cannot use server-side TFO.
1Client-side TFO enabledDefault in upstream kernel docs, but not enough for an Nginx listener.
2Server-side TFO enabledMinimum value for listen ... fastopen=....
3Client and server TFO enabledCommon practical value when the host may also run TFO-capable client tests.

The kernel also defines advanced flags such as 4, 512, and 1024. Do not use those for a basic Nginx setup unless you deliberately need cookie-less behavior or all-listener defaults. The Nginx fastopen=256 parameter already enables the individual listening socket.

Enable TCP Fast Open Temporarily

Use sysctl -w for an immediate test. This change does not survive a reboot. The examples use 3 so the host can also run client-side TFO probes; use 2 when the host should only accept server-side TFO:

sudo sysctl -w net.ipv4.tcp_fastopen=3
net.ipv4.tcp_fastopen = 3

Confirm the active value before editing Nginx:

sysctl net.ipv4.tcp_fastopen
net.ipv4.tcp_fastopen = 3

Enable TCP Fast Open Permanently

Create a dedicated sysctl file when you are ready to keep the setting after reboot:

printf '%s\n' 'net.ipv4.tcp_fastopen = 3' | sudo tee /etc/sysctl.d/99-tcp-fastopen.conf > /dev/null

Load that file immediately:

sudo sysctl -p /etc/sysctl.d/99-tcp-fastopen.conf
net.ipv4.tcp_fastopen = 3

Configure TCP Fast Open in the Nginx listen Directive

The official Nginx listen directive documentation lists fastopen=number as a socket parameter in the server context. The number limits the queue of connections that have sent SYN data but have not completed the three-way handshake.

Back up the exact configuration file you plan to edit. On Debian and Ubuntu, virtual hosts usually live under /etc/nginx/sites-available/. On RHEL-family systems, Fedora, Arch, and many source builds, they often live under /etc/nginx/conf.d/ or the main /etc/nginx/nginx.conf file. If you edit the main file, back it up before changing a listener; for a site include, replace both paths with the active site file shown by nginx -T.

sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup

Add fastopen to an HTTP Nginx Listener

Add fastopen=256 to each TCP listener where you want TFO. If you listen on both IPv4 and IPv6, configure both lines:

server {
    listen 80 fastopen=256;
    listen [::]:80 fastopen=256;
    server_name example.com;

    root /var/www/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Add fastopen to an HTTPS Nginx Listener

For HTTPS, place fastopen=256 alongside the existing TCP socket parameters on the listen directive. Do not invent certificate paths; keep your existing working SSL certificate and key lines:

server {
    listen 443 ssl fastopen=256;
    listen [::]:443 ssl fastopen=256;
    server_name example.com;

    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;

    root /var/www/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Nginx socket parameters apply to an address and port pair, not to a single location. If several server blocks share the same listener, add socket parameters consistently and avoid defining conflicting values for the same address and port.

Choose an Nginx fastopen Queue Size

The value after fastopen= is the pending TFO queue length. It is not a latency multiplier, and larger values are not automatically faster.

  • fastopen=50: Reasonable for low-traffic servers and small test deployments.
  • fastopen=256: A practical starting point for most public web servers.
  • fastopen=512 or higher: Consider only after observing listener overflow or heavy TFO concurrency.

When the TFO queue fills, clients fall back to the normal handshake instead of failing outright. Start with a conservative value and use kernel counters to decide whether the queue needs tuning.

Verify TCP Fast Open in Nginx

Always test the Nginx syntax before reload. This catches misplaced fastopen parameters, missing semicolons, and conflicting listener options before they affect traffic:

sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Reload Nginx only after the syntax test passes:

sudo systemctl reload nginx

Confirm Nginx is listening on the expected TCP port. In ss -ltnp, -l lists listening sockets, -t limits output to TCP, -n keeps numeric ports, and -p adds process details when permission allows it:

sudo ss -ltnp 'sport = :80'

A passing result has a LISTEN row whose local port ends in :80 and, when process details are visible, a process column that names nginx. Process IDs, file descriptors, and queue values vary by host.

Confirm the Nginx fastopen Parameter Loaded

Dump the active Nginx configuration and print each matching fastopen line with its owning file marker. This verifies that you edited the configuration file Nginx actually loaded instead of a disabled include:

sudo nginx -T 2>&1 | awk '
/^# configuration file / { source=$0; next }
/fastopen/ {
    if (source != last_source) {
        print source
        last_source = source
    }
    print
}'

Example output shows the active file before the loaded listener lines:

# configuration file /etc/nginx/conf.d/site.conf:
    listen 80 fastopen=256;
    listen [::]:80 fastopen=256;

Test TCP Fast Open with curl

The curl command in Linux supports --tcp-fastopen when the local curl and operating system expose that feature. Check the option on the client first:

curl --help all | grep -- '--tcp-fastopen'

Relevant output includes the option name:

     --tcp-fastopen                Use TCP Fast Open

If no line appears, that client cannot run this probe; use another Linux client or a curl build that exposes --tcp-fastopen.

Test from a client that has client-side TFO enabled, usually a host where net.ipv4.tcp_fastopen includes value 1. Replace 203.0.113.10 with the Nginx server address:

curl --tcp-fastopen -D - -o /dev/null http://203.0.113.10/

Relevant output starts with a successful HTTP status line:

HTTP/1.1 200 OK

A normal HTTP response only proves the request succeeded. It does not prove TFO was used, because clients can fall back to a regular TCP handshake. Confirm TFO activity with kernel counters after several client requests.

Check TCP Fast Open Kernel Counters

Use nstat to inspect the Fast Open counters before and after several test requests. Values vary by traffic level, so focus on whether relevant counters increase:

nstat -az | grep -i FastOpen

Relevant lines may include:

TcpExtTCPFastOpenActive           0                  0.0
TcpExtTCPFastOpenActiveFail       0                  0.0
TcpExtTCPFastOpenPassive          4                  0.0
TcpExtTCPFastOpenPassiveFail      0                  0.0
TcpExtTCPFastOpenListenOverflow   0                  0.0
TcpExtTCPFastOpenCookieReqd       1                  0.0

For a server-side Nginx test, TcpExtTCPFastOpenPassive or TcpExtTCPFastOpenCookieReqd increasing is the useful signal. If only TcpExtTCPFastOpenActive changes, you are observing client-side TFO from that host rather than server-side TFO accepted by Nginx.

Advanced TCP Fast Open Notes for Production Nginx

Avoid TFO on Non-Idempotent Nginx Endpoints

TFO can cause duplicate early request data to reach the application in rare cases. That is usually acceptable for static files and repeatable GET requests, but it can be unsafe for endpoints that create orders, submit forms, change account state, or trigger backend jobs.

If one address and port serves mixed workloads, test the whole listener. A fastopen parameter on listen 443 can affect every name-based virtual host sharing that socket, even when only one server_name was edited.

Use Edge Verification for Load Balancers and CDNs

When a load balancer, CDN, or reverse proxy terminates TCP before traffic reaches Nginx, test TFO on that edge layer. Enabling TFO on the origin can still help origin-facing connections in some architectures, but it will not remove a visitor-to-edge round trip when the visitor never opens TCP directly to the origin.

Disable TCP Fast Open Cleanly

To roll back the Nginx change, remove fastopen=... from the affected listen lines, then test and reload Nginx:

sudo nginx -t && sudo systemctl reload nginx

If you created /etc/sysctl.d/99-tcp-fastopen.conf during setup, remove it and restore the baseline value you recorded before changing the sysctl. For systems that started at the upstream Linux default, the rollback is:

sudo rm /etc/sysctl.d/99-tcp-fastopen.conf
sudo sysctl -w net.ipv4.tcp_fastopen=1
net.ipv4.tcp_fastopen = 1

If your distribution or hosting image intentionally sets a different value, use that local baseline instead of forcing 1.

Troubleshoot TCP Fast Open in Nginx

Most TFO failures come from one of four places: the kernel value, the Nginx listener, the client, or a proxy layer in front of the server.

Kernel TFO Is Not Enabled for Server Sockets

If the kernel value is 0 or 1, Nginx cannot accept server-side Fast Open data even when the listen line contains fastopen=256.

sysctl net.ipv4.tcp_fastopen
net.ipv4.tcp_fastopen = 1

Set the value to 2 or 3. Use 3 when the same host will also run the curl probe:

sudo sysctl -w net.ipv4.tcp_fastopen=3
net.ipv4.tcp_fastopen = 3

Validate the Nginx configuration and reload only after syntax passes:

sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
sudo systemctl reload nginx

After the reload, repeat the curl probe from the client:

curl --tcp-fastopen -D - -o /dev/null http://203.0.113.10/

Then recheck counters on the Nginx server:

nstat -az | grep -i FastOpen

Nginx Did Not Load the fastopen Parameter

If you edited a disabled virtual host, the active configuration will not show fastopen. Dump the loaded configuration with the owning file marker:

sudo nginx -T 2>&1 | awk '
/^# configuration file / { source=$0; next }
/fastopen/ {
    if (source != last_source) {
        print source
        last_source = source
    }
    print
}'

If the command prints no fastopen line, edit the enabled site file or include file. Then validate and reload:

sudo nginx -t && sudo systemctl reload nginx

Rerun the owner-aware dump; it should print the file marker and the loaded fastopen listener:

sudo nginx -T 2>&1 | awk '
/^# configuration file / { source=$0; next }
/fastopen/ {
    if (source != last_source) {
        print source
        last_source = source
    }
    print
}'

curl Succeeds but TFO Counters Do Not Increase

A successful curl --tcp-fastopen request can still use a regular TCP handshake. On the client that runs curl, check that the value includes client-side TFO:

cat /proc/sys/net/ipv4/tcp_fastopen

Values such as 1 or 3 include client-side TFO. Then run the probe from that client:

curl --tcp-fastopen -D - -o /dev/null http://203.0.113.10/

On the Nginx server, recheck the counters after several direct requests:

nstat -az | grep -i FastOpen

If TcpExtTCPFastOpenPassive and TcpExtTCPFastOpenCookieReqd stay at 0, the connection may not be reaching the origin with TFO. Test a direct origin path or verify TFO support on the load balancer or CDN that terminates the client connection.

Nginx Reports a Duplicate listen Option Error

Conflicting socket parameters on the same address and port can prevent Nginx from loading the configuration. The error usually points to duplicate or inconsistent listen directives:

sudo nginx -t
nginx: [emerg] duplicate listen options for 0.0.0.0:80 in /etc/nginx/conf.d/site.conf:12
nginx: configuration file /etc/nginx/nginx.conf test failed

Keep the socket parameters consistent for each address and port pair. Then test again:

sudo nginx -t

TCP Fast Open affects connection setup only. Pair it with other Nginx tuning only when each feature matches your traffic pattern:

Conclusion

TCP Fast Open is active for the selected Nginx listener once the Linux server-side bit is enabled, fastopen=... appears in the loaded listen directive, and the Fast Open counters move during client tests. Keep it on listeners that can tolerate duplicate early request data, and use the related Nginx performance guides for throughput tuning beyond connection setup.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Verify before posting: