2026年11月12日

2026年11月12日

Nginx tcp_nopush vs tcp_nodelay: What They Do and How to Set Them

This article is a localized edition of the Japanese original. Read the Japanese original

The short answer

Directive Default What it does Recommendation
tcp_nopush off When sending with sendfile, uses TCP_CORK on Linux (TCP_NOPUSH on FreeBSD) to send only full packets on, together with sendfile on
tcp_nodelay on Uses TCP_NODELAY to send even small data without waiting Keep the default on

Both can be set in http, server and location (official Nginx documentation, ngx_http_core_module). For a typical website, these three lines in the http block are all you need.

http {
    sendfile    on;
    tcp_nopush  on;
    tcp_nodelay on;
}

Background: when TCP sends data

Nagle’s algorithm and TCP_NODELAY

TCP has a mechanism that holds back small pieces of data and sends them in batches (Nagle's algorithm). It keeps the link from filling up with tiny packets, but combined with delayed ACKs on the other side it can hold up short responses.

TCP_NODELAY is the socket option that turns Nagle's algorithm off. Nginx's tcp_nodelay defaults to on, and according to the official documentation it is enabled when a connection moves into the keep-alive state. It is also enabled on SSL connections, for unbuffered proxying and for WebSocket proxying.

TCP_CORK and tcp_nopush

TCP_CORK (Linux) does the opposite: it "corks" the socket, and while it is set, partial packets are held instead of sent. With tcp_nopush on, Nginx uses this option when sending with sendfile, and according to the official documentation this lets it:

  • send the response header and the beginning of the file in one packet
  • send the file in full packets

Because a small header-only packet no longer goes out first, fewer packets are sent.

When tcp_nopush helps and when it does not

tcp_nopush takes effect only when sendfile is used (official documentation). sendfile defaults to off, so writing tcp_nopush on without sendfile on does nothing.

sendfile() sends a file on disk straight to the socket inside the kernel, so it is used only when Nginx serves a file as is.

Response type sendfile tcp_nopush
Static files over HTTP (images, CSS, JS) Used Takes effect
Static files over HTTPS Usually not used (Nginx encrypts with OpenSSL before sending) Usually no effect
Responses from PHP-FPM (FastCGI) or a proxied upstream Not used No effect

Over HTTPS, sendfile can be used only in setups that combine OpenSSL 3.0 with kernel TLS (kTLS) (the Nginx changelog lists "support for SSL_sendfile() when using OpenSSL 3.0"). kTLS is not enabled by default, so on most HTTPS sites tcp_nopush has little effect.

For WordPress, the pages PHP generates come from PHP-FPM and are not affected; only images in wp-content/uploads and theme CSS/JS served directly by Nginx are. Enabling it does no harm, but do not expect a visible speed-up.

Why turning both on is not a contradiction

tcp_nopush ("batch it up") and tcp_nodelay ("send now") look like opposites, but Nginx uses them at different times.

  • tcp_nopush: used while a file is being sent with sendfile
  • tcp_nodelay: used when the connection moves into the keep-alive state (after the response is sent, while waiting for the next request), among other cases

While the file is being sent, packets are kept full to reduce their number, and the small last part of the response goes out without waiting. That is why both are commonly set to on.

Setting tcp_nodelay off can hold up small responses on keep-alive connections, so leave it at the default on unless you have a specific reason.

Configuration steps

1. Check the current settings

The default nginx.conf differs by distributor. In the official Nginx Docker image (stable as of October 2026), for example, sendfile on; is active and #tcp_nopush on; is commented out. Check the full configuration that is actually loaded.

sudo nginx -T 2>/dev/null | grep -nE 'sendfile|tcp_nopush|tcp_nodelay'

2. Add the settings

Open /etc/nginx/nginx.conf. Edit the http block in this file. If a directive is already there, change its value instead of adding it again (the same directive twice in one block makes nginx -t fail with an error such as "sendfile" directive is duplicate).

http {
    sendfile    on;
    tcp_nopush  on;
    tcp_nodelay on;

    # ... existing settings ...
}

To apply it only where you serve video or other large files, you can put it in a location.

location /video/ {
    sendfile   on;
    tcp_nopush on;
}

3. Check the syntax and apply

There is no need to stop Nginx. Check the syntax, and if it passes, reload the configuration.

sudo nginx -t
sudo systemctl reload nginx

If nginx -t does not print syntax is ok and test is successful, do not reload; fix the line it reports.

4. Verify after applying

# Values in effect
sudo nginx -T 2>/dev/null | grep -nE 'sendfile|tcp_nopush|tcp_nodelay'

# Static files are served normally
curl -sI https://example.com/wp-includes/js/jquery/jquery.min.js | head -n 1

Caveats

  • Shared folders and network file systems: on virtual machine shared folders and similar setups, sendfile is known to serve stale content. If file changes do not show up in a development environment, set sendfile off; there only (tcp_nopush then stops working too).
  • Measuring the effect: the impact on speed depends on the network and file sizes. Compare the same requests before and after the change and decide based on the numbers.
  • Interaction with directio: with directio, sendfile is not used for the requests it applies to (official documentation).

Summary

  • tcp_nopush only works with sendfile; it sends the header together with the start of the file, and the file in full packets. Default: off.
  • tcp_nodelay turns off Nagle's algorithm. Default: on; used on keep-alive and SSL connections.
  • For most sites, sendfile on; tcp_nopush on; tcp_nodelay on; is fine.
  • HTTPS (without kTLS) and PHP responses do not use sendfile, so tcp_nopush has limited effect.
  • After a change, apply it with nginx -t and systemctl reload nginx, and confirm the values with nginx -T.

For configuring sendfile itself, see Enabling sendfile and tcp_nopush in Nginx; for an overview of nginx.conf, see Basic nginx.conf settings.

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲