{"id":8196,"date":"2026-06-10T12:06:18","date_gmt":"2026-06-10T12:06:18","guid":{"rendered":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/haydenjames.io\/?p=8196"},"modified":"2026-06-10T14:36:41","modified_gmt":"2026-06-10T14:36:41","slug":"nginx-tuning-tips-tls-ssl-https-ttfb-latency","status":"publish","type":"post","link":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/","title":{"rendered":"Nginx tuning tips: HTTPS\/TLS &#8211; Turbocharge TTFB\/Latency"},"content":{"rendered":"<p>Nginx TLS tuning won&#8217;t fix a slow application, but it does cut handshake overhead and improve connection reuse, which shaves milliseconds off every HTTPS request. This guide covers the TLS, HTTP\/2, and HTTP\/3 settings I use to keep Nginx fast without giving up modern security. The goal is lower TTFB (Time To First Byte) and reduced latency.<\/p><div class=\"hayden-after-paragraph hayden-entity-placement\" id=\"hayden-2066509331\"><div data-nosnippet id=\"hayden-3736762855\" style=\"margin-left: auto;margin-right: auto;text-align: center;\"><a data-no-instant=\"1\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/betterstack.com\/\" rel=\"noopener nofollow sponsored\" class=\"a2t-link\" target=\"_blank\" aria-label=\"Linux Logs and metrics: Better Stack\"><img fetchpriority=\"high\" loading=\"eager\" decoding=\"async\" src=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2025\/04\/logs-and-metrics-wide.png\" alt=\"Linux Logs and metrics: Better Stack\"  srcset=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2025\/04\/logs-and-metrics-wide.png 868w, https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2025\/04\/logs-and-metrics-wide-300x104.png 300w, https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2025\/04\/logs-and-metrics-wide-560x194.png 560w\" sizes=\"(max-width: 868px) 100vw, 868px\" width=\"868\" height=\"300\"  style=\"display: inline-block;\" \/><\/a><\/div><div align=\"center\" style=\"font-style: italic; font-size: 0.85em; font-weight: normal; margin-top: 4px;\">\r\n\tAdvertisement\r\n<\/div><\/div>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 ez-toc-wrap-center counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><div class=\"ez-toc-title\" style=\"cursor:inherit\">In This Article<\/div>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Are_SSL_certificates_using_SSL_or_TLS\" >Are SSL certificates using SSL or TLS?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#The_importance_of_TLS_12_TLS_13\" >The importance of TLS 1.2 &amp; TLS 1.3<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#How_much_can_TLS_tuning_actually_improve_TTFB\" >How much can TLS tuning actually improve TTFB?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Enable_HTTP2_and_HTTP3_QUIC_on_Nginx\" >Enable HTTP\/2 and HTTP\/3 &amp; QUIC on Nginx<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Enable_HTTP3_with_QUIC\" >Enable HTTP\/3 with QUIC<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Check_if_HTTP2_or_HTTP3_is_enabled_using_Google_Chrome\" >Check if HTTP\/2 or HTTP\/3 is enabled using Google Chrome<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Check_if_HTTP2_or_HTTP3_is_enabled_using_the_command_line\" >Check if HTTP\/2 or HTTP\/3 is enabled using the command line<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Enable_SSL_session_cache\" >Enable SSL session cache<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Disable_SSL_session_tickets\" >Disable SSL session tickets<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Disable_old_TLS_versions_and_decide_on_TLS_12\" >Disable old TLS versions (and decide on TLS 1.2)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Enable_OCSP_Stapling\" >Enable OCSP Stapling<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Reduce_SSL_buffer_size\" >Reduce SSL buffer size<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Full_Nginx_SSL_config_for_improved_TTFB\" >Full Nginx SSL config for improved TTFB<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#Enable_HTTP_Strict_Transport_Security_HSTS\" >Enable HTTP Strict Transport Security (HSTS)<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#HTTP2_reference_and_useful_reading\" >HTTP\/2 reference and useful reading<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/nginx-tuning-tips-tls-ssl-https-ttfb-latency\/#HTTP3_QUIC_reference_and_useful_reading\" >HTTP\/3 &amp; QUIC reference and useful reading<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Are_SSL_certificates_using_SSL_or_TLS\"><\/span>Are SSL certificates using SSL or TLS?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Online, we still use the term &#8220;SSL&#8221; (Secure Sockets Layer) to refer to the encryption protocol used for secure communication, even though they are actually using TLS. For example, SSL certificates are used to establish a secure connection between a client and a server over the internet. However, SSL itself is considered deprecated and insecure, and modern encryption protocols such as TLS are used instead.<\/p>\n<p>Also, the term &#8220;SSL certificate&#8221; still lives on and is used informally to refer to digital certificates, even though the actual protocol being used is TLS. That said, it&#8217;s important to note that TLS should be used instead of SSL, as it is more secure and provides better protection against attacks.<\/p>\n<p>To promote the use of secure encryption protocols, it&#8217;s recommended to start using terms like &#8220;TLS&#8221; and &#8220;TLS certificate&#8221; in our emails and communications. In fact, as I update this article, I&#8217;ll be removing much of the instances of the term SSL.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"The_importance_of_TLS_12_TLS_13\"><\/span>The importance of TLS 1.2 &amp; TLS 1.3<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Online security is a major concern for both individuals and businesses. Encryption plays a vital role in safeguarding online data, and one of the most popular encryption protocols is the Transport Layer Security (TLS) protocol. Let&#8217;s briefly look at the importance of TLS 1.2 and TLS 1.3.<\/p>\n<p>Since 30th June 2018, the PCI Security Standards Council has required that support for SSL 3.0 and TLS 1.0 be disabled and, more recently, to also disable TLS 1.1. So that, as of updating this article, using <strong>TLS 1.2 and 1.3 is strongly recommended<\/strong>. In addition, Google Chrome began marking &#8216;HTTP&#8217; websites as \u201c<a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/security.googleblog.com\/2018\/02\/a-secure-web-is-here-to-stay.html\" target=\"_blank\" rel=\"noopener noreferrer\">not secure<\/a>\u201d back in 2018, and the web has since moved almost entirely to HTTPS. As of 2026, around 95% of web traffic loads over HTTPS and the web&#8217;s top 100 websites all use <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/transparencyreport.google.com\/https\/overview?hl=en\" target=\"_blank\" rel=\"noopener noreferrer\">HTTPS by default<\/a>.<\/p>\n<p>With this in mind, let&#8217;s look at Nginx TLS tuning tips to improve the performance of Nginx + HTTPS for better <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/analyze-websites-ttfb-time-first-byte\/\" target=\"_blank\" rel=\"noopener noreferrer\">TTFB<\/a> and reduced latency.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"How_much_can_TLS_tuning_actually_improve_TTFB\"><\/span>How much can TLS tuning actually improve TTFB?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Before we get into the config, a reality check. TLS tuning helps, but for most sites it isn&#8217;t where the big TTFB numbers come from.<\/p>\n<p>On a typical WordPress, PHP, or application backend, the time to first byte is dominated by what happens <em>after<\/em> the handshake: PHP execution, database queries, cache hits and misses, how far the visitor sits from your origin, and your CDN setup. Shaving milliseconds off the TLS handshake is real, and on a fast backend it&#8217;s noticeable, but it won&#8217;t rescue a site that spends 800ms building the page.<\/p>\n<p>So treat the tips below as one layer. Get them right because they&#8217;re cheap and they compound, then spend the rest of your effort on caching, your database, and your <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/best-cdn-providers\/\" target=\"_blank\" rel=\"noopener noreferrer\">CDN<\/a>.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Enable_HTTP2_and_HTTP3_QUIC_on_Nginx\"><\/span>Enable HTTP\/2 and HTTP\/3 &amp; QUIC on Nginx<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-22427 size-large\" title=\"Enable HTTP\/2 and HTTP\/3 &amp; QUIC on Nginx\" src=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2023\/11\/nginx-ttfb-tuning-868x456.jpg\" alt=\"Enable HTTP\/2 and HTTP\/3 &amp; QUIC on Nginx\" width=\"868\" height=\"456\" srcset=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2023\/11\/nginx-ttfb-tuning-868x456.jpg 868w, https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2023\/11\/nginx-ttfb-tuning-300x158.jpg 300w, https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2023\/11\/nginx-ttfb-tuning-560x294.jpg 560w\" sizes=\"auto, (max-width: 868px) 100vw, 868px\" \/><\/p>\n<p>The first step in tuning Nginx for faster TTFB\/latency with HTTPS is to ensure that at least <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/http2.github.io\" target=\"_blank\" rel=\"noopener noreferrer\">HTTP\/2<\/a> is enabled. HTTP\/2 was first implemented in Nginx version 1.9.5 to replace <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.chromium.org\/spdy\" target=\"_blank\" rel=\"noopener noreferrer\">spdy<\/a>. (Remember: HTTP\/2 requires HTTPS)<\/p>\n<p>If you set this up years ago, your config probably looks like this:<\/p>\n<pre>listen 443 ssl http2;<\/pre>\n<p>That still works, but since Nginx 1.25.1 the <em>http2<\/em> parameter on the <em>listen<\/em> directive is deprecated. Run <code>nginx -t<\/code> on a current build and you&#8217;ll see the warning. The fix is to move HTTP\/2 onto its own directive:<\/p>\n<pre>listen 443 ssl;\r\nhttp2 on;<\/pre>\n<p>The <code>http2<\/code> directive enables the protocol per server block, which is cleaner than tying it to every <em>listen<\/em> line. If you run a fleet of servers, check that every box is on 1.25.1 or newer before you switch, since an older Nginx won&#8217;t recognize <code>http2 on;<\/code> and will fail to start.<\/p>\n<h4><span class=\"ez-toc-section\" id=\"Enable_HTTP3_with_QUIC\"><\/span>Enable HTTP\/3 with QUIC<span class=\"ez-toc-section-end\"><\/span><\/h4>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-13623\" title=\"HTTP-v1-v2-v3-stacks\" src=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2021\/06\/HTTP-v1-v2-v3-stacks.png\" alt=\"HTTP-v1-v2-v3-stacks\" width=\"868\" height=\"322\" \/><\/p>\n<p>When I first wrote the HTTP\/3 part of this article, enabling it meant patching and compiling Nginx from source against a QUIC-capable TLS library. That era is over. Native QUIC and HTTP\/3 support shipped in the Nginx mainline starting with 1.25.0 and has since matured into the stable branch, so on a recent distro or the official Nginx repo you no longer build it by hand.<\/p>\n<p>Despite years of excitement around HTTP\/3, real-world adoption has been slower than expected. By mid-2026, HTTP\/2 serves just over half of all requests while HTTP\/3 sits near 21% and has plateaued for several months (<a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/w3techs.com\/technologies\/details\/ce-http3\" target=\"_blank\" rel=\"noopener noreferrer\">source<\/a>). Part of that gap is structural: a browser only upgrades to HTTP\/3 after it discovers support through an <code>Alt-Svc<\/code> header or DNS record, so plenty of first-visit page loads never negotiate QUIC at all. HTTP\/3 is still worth enabling. It moves the transport to UDP and removes TCP head-of-line blocking, which helps most on lossy or high-latency mobile connections. Just don&#8217;t expect every visitor to arrive over it.<\/p>\n<p>On Nginx 1.25.0 or newer with QUIC support built in, a server block looks like this:<\/p>\n<pre>server {\r\n    listen 443 ssl;\r\n    listen [::]:443 ssl;\r\n    listen 443 quic reuseport;\r\n    listen [::]:443 quic reuseport;\r\n\r\n    http2 on;\r\n\r\n    ssl_certificate     \/path\/to\/your\/certificate.pem;\r\n    ssl_certificate_key \/path\/to\/your\/key.pem;\r\n\r\n    # Advertise HTTP\/3 to clients arriving over HTTP\/1.1 or HTTP\/2\r\n    add_header Alt-Svc 'h3=\":443\"; ma=86400';\r\n\r\n    # ... rest of your server config\r\n}<\/pre>\n<p>One caveat on <code>reuseport<\/code>: specify it only once per IP and port combination. If you run multiple server blocks on the same address, put <code>reuseport<\/code> on the default block only and use <code>listen 443 quic;<\/code> on the rest, or Nginx will refuse to start.<\/p>\n<p>The <code>Alt-Svc<\/code> header is the part people forget. Without it, browsers have no way to know your server speaks HTTP\/3, so they stay on HTTP\/2. Reload and test:<\/p>\n<pre>nginx -t\r\nnginx -s reload<\/pre>\n<p>If your distro&#8217;s Nginx package was built without the QUIC module, check the <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/docs.nginx.com\/nginx\/admin-guide\/installing-nginx\/installing-nginx-open-source\/\" target=\"_blank\" rel=\"noopener\">official install guide<\/a> for a build that includes it rather than compiling from source.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Check_if_HTTP2_or_HTTP3_is_enabled_using_Google_Chrome\"><\/span>Check if HTTP\/2 or HTTP\/3 is enabled using Google Chrome<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>To confirm if HTTP\/2 or HTTP\/3 is enabled:<\/p>\n<p>&gt; open your website in Google Chrome<br \/>\n&gt; right-click anywhere on the web page and select <em>Inspect<\/em><br \/>\n&gt; click the <em>Network<\/em> tab<br \/>\n&gt; press F5 (on your keyboard) or refresh your web page manually<br \/>\n&gt; the <em>Protocol<\/em> column should now show <strong>h<em>2<\/em><\/strong> or <strong>h3<\/strong> for all assets loaded via your server<br \/>\n&gt; If the Protocol column is missing, you can add it using right-click.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-17542 size-large\" title=\"Google Chrome inspect network http\/2 (h2), http\/3 (h3) check.\" src=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2022\/05\/check-http2-http3-h2-h3-chrome-inspect-868x463.png\" alt=\"Google Chrome inspect network http\/2 (h2), http\/3 (h3) check.\" width=\"868\" height=\"463\" srcset=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2022\/05\/check-http2-http3-h2-h3-chrome-inspect-868x463.png 868w, https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2022\/05\/check-http2-http3-h2-h3-chrome-inspect-300x160.png 300w, https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2022\/05\/check-http2-http3-h2-h3-chrome-inspect-560x299.png 560w\" sizes=\"auto, (max-width: 868px) 100vw, 868px\" \/><br \/>\n<em>Google Chrome inspect network http\/2 (h2), http\/3 (h3) check.<\/em><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Check_if_HTTP2_or_HTTP3_is_enabled_using_the_command_line\"><\/span>Check if HTTP\/2 or HTTP\/3 is enabled using the command line<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>To test from your Linux\/Mac command line with curl:<br \/>\n<em>(Don&#8217;t also forget to curl test your CDN-hosted requests. Example: cdn.domain.com.<br \/>\n<\/em><em><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/best-cdn-providers\/\" target=\"_blank\" rel=\"noopener noreferrer\">Compare KeyCDN, BunnyCDN and other CDN providers which support HTTP\/2<\/a>)<\/em><\/p>\n<pre>curl --http2 -I https:\/\/round-lake.dustinice.workers.dev:443\/https\/domain.com\/<\/pre>\n<pre>curl --http3 -I https:\/\/round-lake.dustinice.workers.dev:443\/https\/domain.com\/<\/pre>\n<p>If the<em> &#8211;http3<\/em> command does not work, you can also <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.http3check.net\/\" target=\"_blank\" rel=\"noopener\">check here<\/a>.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Enable_SSL_session_cache\"><\/span>Enable SSL session cache<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>With HTTPS connections, instead of end-users connecting via one round trip (request sent, then the server responds), the connection needs an extra handshake. However, using HTTP\/2 and enabling Nginx <em>ssl_session_cache<\/em> will ensure faster HTTPS performance for initial connections and <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/http\/www.httpvshttps.com\" target=\"_blank\" rel=\"noopener noreferrer\">faster-than-http<\/a> page loads.<\/p>\n<p>Using the option<em> ssl_session_cache shared:SSL:[size], <\/em>you can configure Nginx to share cache between all worker processes. One megabyte can store about 4000 sessions. You&#8217;ll also want to specify the time during (cache TTL) allowed for reuse:<\/p>\n<pre>ssl_session_cache shared:SSL:1m; # holds approx 4000 sessions\r\nssl_session_timeout 1h; # 1 hour during which sessions can be re-used.<\/pre>\n<h2><span class=\"ez-toc-section\" id=\"Disable_SSL_session_tickets\"><\/span>Disable SSL session tickets<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-8449 size-full\" title=\"ssl handshake\" src=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-content\/uploads\/2018\/06\/ssl_handshak.gif\" alt=\"ssl handshake\" width=\"568\" height=\"512\" \/><\/p>\n<p>Because the proper rotation of session ticket encryption key is <del><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/github.com\/mozilla\/server-side-tls\/issues\/135\" target=\"_blank\" rel=\"noopener noreferrer\">not yet implemented in Nginx<\/a>, you should turn this off for now.<\/del><\/p>\n<pre><del>ssl_session_tickets off;<\/del><\/pre>\n<p><strong>Update:<\/strong> Since <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/github.com\/mozilla\/server-side-tls\/issues\/284\" target=\"_blank\" rel=\"noopener\">Nginx 1.23.2<\/a>, ticket key handling for stateless session resumption is much improved, so the old reason to disable it is gone. Unless you run a multi-server setup without synchronized ticket keys, keep this on:<\/p>\n<pre>ssl_session_tickets on;<\/pre>\n<p>If you run multiple load-balanced Nginx servers, remember that session ticket keys need to be shared and rotated consistently across the fleet, otherwise resumption breaks and you lose the benefit.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Disable_old_TLS_versions_and_decide_on_TLS_12\"><\/span>Disable old TLS versions (and decide on TLS 1.2)<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>As we&#8217;ve discussed in the opening, HTTPS and HTTP\/2(3) are a move toward the latest, fast and most secure web technology, and the protocol floor has risen with it. TLS 1.0 and 1.1 are obsolete, blocked by every current browser, and disallowed under <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/blog.pcisecuritystandards.org\/migrating-from-ssl-and-early-tls\" target=\"_blank\" rel=\"noopener noreferrer\">PCI DSS<\/a>. They should be off everywhere.<\/p>\n<p>That leaves the real decision: TLS 1.2 and 1.3, or 1.3 only.<\/p>\n<p>For most public-facing sites, keep both enabled:<\/p>\n<pre>ssl_protocols TLSv1.2 TLSv1.3;<\/pre>\n<p>TLS 1.3 is the one that helps TTFB. It cuts the handshake to a single round trip and supports session resumption, so returning visitors connect faster. TLS 1.2 stays in the list as a fallback for the occasional older client, and on a normal site it costs you nothing to leave it on.<\/p>\n<p>Go TLS 1.3 only when you control the clients, an internal API, an app backend, or a service where you know nothing old needs to connect:<\/p>\n<pre>ssl_protocols TLSv1.3;<\/pre>\n<p>Disabling TLS 1.2 on a public site is the kind of change that looks clean in a config file and then quietly drops a slice of real traffic. Unless you have a specific reason, leave it on. (TLS 1.3 needs Nginx 1.13 or newer.)<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Enable_OCSP_Stapling\"><\/span>Enable OCSP Stapling<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>OCSP (Online Certificate Status Protocol) stapling lets Nginx attach a time-stamped, CA-signed proof of certificate validity to the TLS handshake, so the client doesn&#8217;t make its own round trip to the CA to check revocation. For years this was a solid TTFB win on cold connections, and the config still looks like this:<\/p>\n<pre>ssl_stapling on;\r\nssl_stapling_verify on;\r\nssl_trusted_certificate \/path\/to\/full_chain.pem;\r\nresolver 8.8.8.8 8.8.4.4 valid=300s;\r\nresolver_timeout 5s;<\/pre>\n<p>Here&#8217;s what changed, and it matters if you use Let&#8217;s Encrypt. Let&#8217;s Encrypt <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/letsencrypt.org\/2024\/12\/05\/ending-ocsp\/\" target=\"_blank\" rel=\"noopener noreferrer\">ended OCSP support<\/a> and shut off its responders on August 6, 2025. Certificates it issues now ship with no OCSP URL and a CRL URL instead. With no responder to query, <code>ssl_stapling on;<\/code> does nothing on a Let&#8217;s Encrypt certificate and Nginx logs an <code>\"ssl_stapling\" ignored, no OCSP responder URL<\/code> warning.<\/p>\n<p>So the honest 2026 take: OCSP stapling is no longer one of the main TTFB levers. If your CA still publishes an OCSP URL, stapling remains a small, harmless win and you can keep it on. If you&#8217;re on Let&#8217;s Encrypt, the directives above are now inert, and you can drop them to keep your config clean and your logs quiet. The industry is moving revocation toward CRLs and short-lived certificates, and this is part of that shift.<\/p>\n<p>Note: <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/http\/nginx.org\/en\/docs\/http\/ngx_http_ssl_module.html\" target=\"_blank\" rel=\"noopener noreferrer\">ssl_trusted_certificate<\/a> specifies the trusted CA certificate chain file, in PEM format, used to verify OCSP responses where they still apply.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Reduce_SSL_buffer_size\"><\/span>Reduce SSL buffer size<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The Nginx <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/http\/nginx.org\/en\/docs\/http\/ngx_http_ssl_module.html#ssl_buffer_size\" target=\"_blank\" rel=\"noopener noreferrer\">ssl_buffer_size<\/a> config option sets the size of the buffer used for sending data via HTTPS. By default, the buffer is set to 16k, a one-size-fits-all approach geared toward big responses. However, to minimize TTFB (Time To First Byte), it is often better to use a smaller value, for example:<br \/>\n<em>(I was able to shave about 30 &#8211; 50ms off TTFB. Your mileage may vary.)<\/em><\/p>\n<pre>ssl_buffer_size 4k;<\/pre>\n<h2><span class=\"ez-toc-section\" id=\"Full_Nginx_SSL_config_for_improved_TTFB\"><\/span>Full Nginx SSL config for improved TTFB<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Pasted below my full Nginx TLS config for this blog, updated for 2026. The <code>ssl_ciphers<\/code> string only affects TLS 1.2 clients; TLS 1.3 negotiates its own suites.<\/p>\n<pre>http2 on;\r\nssl_protocols TLSv1.2 TLSv1.3;\r\nssl_prefer_server_ciphers off;\r\nssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';\r\nssl_session_cache shared:SSL:10m;\r\nssl_session_timeout 1d;\r\nssl_session_tickets on;\r\nssl_buffer_size 4k;<\/pre>\n<p>A few notes on what changed from the older version of this block. With TLS 1.3 the cipher suites are fixed by the protocol, so a long custom <code>ssl_ciphers<\/code> string and a manual <code>ssl_ecdh_curve<\/code> line buy you almost nothing. The ciphers above only apply to TLS 1.2 connections, and <code>ssl_prefer_server_ciphers<\/code> is now off because modern clients pick sensibly on their own. Rather than hand-tuning this forever, generate a current config from the <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/ssl-config.mozilla.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Mozilla SSL Configuration Generator<\/a> and paste in the parts you need.<\/p>\n<p>Test config, then reload Nginx after changes:<\/p>\n<pre>nginx -t\r\nnginx -s reload<\/pre>\n<h2><span class=\"ez-toc-section\" id=\"Enable_HTTP_Strict_Transport_Security_HSTS\"><\/span>Enable HTTP Strict Transport Security (HSTS)<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Another Nginx HTTPS tip is to enable <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/hstspreload.org\" target=\"_blank\" rel=\"noopener noreferrer\">HSTS preload<\/a>. HTTP Strict Transport Security (HSTS) is a header that allows a web server to declare a policy that browsers will only connect to using secure HTTPS connections and ensures end users do not \u201cclick-through\u201d critical security warnings. (locks clients to HTTPS) This policy enforcement protects secure websites from downgrade attacks, SSL stripping, and cookie hijacking. Also, see https:\/\/round-lake.dustinice.workers.dev:443\/https\/hstspreload.org\/#submission-requirements.<\/p>\n<pre>add_header Strict-Transport-Security \"max-age=63072000; includeSubdomains; preload\";<\/pre>\n<p>Other headers I set in my Nginx config for this blog:<\/p>\n<pre>add_header X-Frame-Options sameorigin; # read <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/X-Frame-Options\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>\r\nadd_header X-Content-Type-Options nosniff; # read <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/X-Content-Type-Options\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a><\/pre>\n<p>If you&#8217;ve carried an <code>X-Xss-Protection \"1; mode=block\"<\/code> line in your config for years, drop it. The browser XSS auditor it controlled has been removed from every major browser, and in some cases the header can introduce vulnerabilities rather than prevent them. A <a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Content-Security-Policy\" target=\"_blank\" rel=\"noopener noreferrer\">Content-Security-Policy<\/a> is the modern replacement.<br \/>\nAlso, see <strong><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/analyze-websites-ttfb-time-first-byte\/\" target=\"_blank\" rel=\"noopener noreferrer\">Analyze Your Website&#8217;s TTFB (Time to First Byte)<\/a>.<\/strong><\/p>\n<h2><span class=\"ez-toc-section\" id=\"HTTP2_reference_and_useful_reading\"><\/span><strong>HTTP\/2 reference and useful reading<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ul>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers<\/a> &#8211; HTTP headers<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/weakdh.org\/sysadmin.html\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/weakdh.org\/sysadmin.html<\/a> &#8211; Guide to Deploying Diffie-Hellman for TLS<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/ssl-config.mozilla.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/ssl-config.mozilla.org\/<\/a> &#8211; Mozilla SSL Configuration Generator<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.ssllabs.com\/ssltest\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.ssllabs.com\/ssltest\/<\/a> &#8211; SSL Server Test<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.nginx.com\/blog\/http2-module-nginx\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.nginx.com\/blog\/http2-module-nginx\/<\/a> &#8211; The HTTP\/2 Module<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/istlsfastyet.com\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/istlsfastyet.com<\/a> &#8211; Is TLS Fast Yet?<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/http\/www.httpvshttps.com\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/http\/www.httpvshttps.com<\/a> &#8211; HTTP vs HTTPS Test<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/free-linux-server-monitoring-apm-sysadmins\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/free-linux-server-monitoring-apm-sysadmins\/<\/a> &#8211; Free web server monitoring<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"HTTP3_QUIC_reference_and_useful_reading\"><\/span><strong>HTTP\/3 &amp; QUIC reference and useful reading<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2><div class=\"hayden-end-of-article hayden-entity-placement\" id=\"hayden-3820273158\"><div data-nosnippet id=\"hayden-1776651984\" style=\"margin-left: auto;margin-right: auto;text-align: center;\"><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.manageengine.com\/it-operations-management\/infrastructure-observability\/server-observability.html?utm_source=linuxblog&#038;utm_medium=bannerad&#038;utm_campaign=ServerObservability\" data-bid=\"1\" data-no-instant=\"1\" rel=\"noopener nofollow sponsored\">\r\n  <img fetchpriority=\"high\" src=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/static.linuxblog.io\/wp-content\/uploads\/2026\/06\/868\u00d7300V3_x1.png\"\r\n       srcset=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/static.linuxblog.io\/wp-content\/uploads\/2026\/06\/868\u00d7300V3_x1.png 1x,\r\n               https:\/\/round-lake.dustinice.workers.dev:443\/https\/static.linuxblog.io\/wp-content\/uploads\/2026\/06\/868\u00d7300V3.png 2x\"\r\n       alt=\"ManageEngine Site24x7 - Fix Linux issues in minutes, not hours!\"\r\n       width=\"868\" height=\"300\"\r\n       loading=\"eager\"\r\n       style=\"display:block;\">\r\n<\/a><\/div><div align=\"center\" style=\"font-style: italic; font-size: 0.85em; font-weight: normal; margin-top: 4px;\">\r\n\tAdvertisement\r\n<\/div><\/div>\n<ul>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.nginx.com\/resources\/glossary\/quic-http3\/\" target=\"_blank\" rel=\"noopener\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.nginx.com\/resources\/glossary\/quic-http3\/<\/a> &#8211; What are QUIC &amp; HTTP\/3<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/http3-explained.haxx.se\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/http3-explained.haxx.se\/<\/a> &#8211; HTTP\/3 explained<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.akamai.com\/blog\/developers\/a-quick-introduction-http3\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.akamai.com\/blog\/developers\/a-quick-introduction-http3<\/a> &#8211; A QUICk Introduction to HTTP\/3<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.chromium.org\/quic\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/www.chromium.org\/quic<\/a> &#8211; Chromium: QUIC, a multiplexed stream transport over UDP.<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/github.com\/quicwg\/base-drafts\/wiki\/Implementations\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/github.com\/quicwg\/base-drafts\/wiki\/Implementations<\/a> &#8211; List of QUIC implementations.<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/blog.cloudflare.com\/tag\/http3\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/blog.cloudflare.com\/tag\/http3\/<\/a> &#8211; Cloudflare on HTTP\/3.<\/li>\n<li><a href=\"https:\/\/round-lake.dustinice.workers.dev:443\/https\/datatracker.ietf.org\/doc\/html\/draft-ietf-quic-http-34\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/round-lake.dustinice.workers.dev:443\/https\/datatracker.ietf.org\/doc\/html\/draft-ietf-quic-http-34<\/a> &#8211; Hypertext Transfer Protocol Version 3, draft-ietf-quic-http-34.<\/li>\n<\/ul>\n<p style=\"text-align: left;\"><em>Published: June 30th, 2018 | Last updated: June 10th, 2026<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nginx TLS tuning won&#8217;t fix a slow application, but it does cut handshake overhead and improve connection reuse, which shaves milliseconds off every HTTPS request. This guide covers the TLS, HTTP\/2, and HTTP\/3 settings I use to keep Nginx fast without giving up modern security. The goal is lower TTFB (Time To First Byte) and [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"publish_to_discourse":"0","publish_post_category":"54","wpdc_auto_publish_overridden":"1","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"1692","discourse_permalink":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxcommunity.io\/t\/nginx-tuning-tips-https-tls-turbocharge-ttfb-latency\/649","wpdc_publishing_response":"","wpdc_publishing_error":"","footnotes":""},"categories":[1,11],"tags":[102,45,35,46,49],"class_list":["post-8196","post","type-post","status-publish","format-standard","hentry","category-articles","category-linux","tag-nginx","tag-performance","tag-security","tag-server","tag-sysadmins"],"_links":{"self":[{"href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-json\/wp\/v2\/posts\/8196","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-json\/wp\/v2\/comments?post=8196"}],"version-history":[{"count":3,"href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-json\/wp\/v2\/posts\/8196\/revisions"}],"predecessor-version":[{"id":22428,"href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-json\/wp\/v2\/posts\/8196\/revisions\/22428"}],"wp:attachment":[{"href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-json\/wp\/v2\/media?parent=8196"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-json\/wp\/v2\/categories?post=8196"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/linuxblog.io\/wp-json\/wp\/v2\/tags?post=8196"}],"curies":[{"name":"wp","href":"https:\/\/round-lake.dustinice.workers.dev:443\/https\/api.w.org\/{rel}","templated":true}]}}