{"id":39300,"date":"2026-07-07T03:35:00","date_gmt":"2026-07-06T20:35:00","guid":{"rendered":"https:\/\/dps.media\/sua-loi-cloudflare-khong-cache-trung-lap-cache-control-no-cache\/"},"modified":"2026-07-07T03:35:00","modified_gmt":"2026-07-06T20:35:00","slug":"fix-cloudflare-not-caching-always-revalidated-expired-due-to-duplicate-cache-control-no-cache","status":"publish","type":"post","link":"https:\/\/dps.media\/en\/fix-cloudflare-not-caching-always-revalidated-expired-due-to-duplicate-cache-control-no-cache\/","title":{"rendered":"Fix Cloudflare not caching (always REVALIDATED\/EXPIRED) due to duplicate Cache-Control: no-cache on OpenLiteSpeed and Nginx Reverse Proxy"},"content":{"rendered":"<p>One of the common issues preventing Cloudflare from caching a website (always returning status <code data-no-translation=\"\">REVALIDATED<\/code> ho\u1eb7c <code data-no-translation=\"\">EXPIRED<\/code> instead of <code data-no-translation=\"\">HIT<\/code>) is the presence of the header <code data-no-translation=\"\">Cache-Control: no-cache<\/code> from the origin server. This article will guide you through detailed diagnosis and a complete fix for this issue on systems using Nginx as a Reverse Proxy in front of OpenLiteSpeed.<\/p>\n<h2>1. Symptoms of the issue<\/h2>\n<p>When checking the Response Headers of your website or static files (such as CSS, JS, and images) using the curl command or Developer Tools (F12) in your browser, you see the following headers appearing at the same time:<\/p>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">Cache-Control: public, max-age=2592000\nCache-Control: no-cache\nCf-Cache-Status: EXPIRED (ho\u1eb7c REVALIDATED)<\/code><\/pre>\n<p>The simultaneous presence of two conflicting <code data-no-translation=\"\">Cache-Control<\/code> headers confuses Cloudflare. The <code data-no-translation=\"\">no-cache<\/code> header forces Cloudflare to send a revalidation request to the origin server on every visit, increasing response time (TTFB) and overloading your origin server.<\/p>\n<h2>2. Diagnosis process and root-cause identification<\/h2>\n<p>To resolve this issue completely, we need to go through steps to isolate the cause:<\/p>\n<ul>\n<li><strong>Step 1: Check plugins and .htaccess:<\/strong> Many people often assume the issue is caused by WordPress cache plugins (such as LiteSpeed Cache) or the <code data-no-translation=\"\">.htaccess<\/code>. file. However, if you use OpenLiteSpeed, it usually ignores header configurations (such as <code data-no-translation=\"\">mod_headers<\/code>) in the file <code data-no-translation=\"\">.htaccess<\/code>.<\/li>\n<li><strong>Step 2: Check the Origin Server IP directly:<\/strong> Run curl directly against the origin server IP (bypassing Cloudflare) to see which headers are generated at the server:\n<pre data-no-translation=\"\"><code data-no-translation=\"\">curl -I -k -H \"Host: yourdomain.com\" https:\/\/[SERVER_IP]\/wp-includes\/css\/dist\/block-library\/style.min.css<\/code><\/pre>\n<p>    If the <code data-no-translation=\"\">Server: nginx<\/code> header appears together with <code data-no-translation=\"\">x-turbo-charged-by: LiteSpeed<\/code>, your system is definitely running an Nginx Reverse Proxy model in front of OpenLiteSpeed.\n  <\/li>\n<\/ul>\n<h2>3. Complete solution<\/h2>\n<h3>Step 1: Remove the hardcoded configuration line in Nginx<\/h3>\n<p>When configuring a Reverse Proxy on control panels such as aaPanel, the system often automatically adds a cache-prevention line in Nginx to avoid dynamic-data issues for Node.js\/Python applications. You need to remove it.<\/p>\n<p>Open the Nginx configuration file for the domain (usually located at <code data-no-translation=\"\">\/www\/server\/panel\/vhost\/nginx\/yourdomain.com.conf<\/code>), find the configuration block <code data-no-translation=\"\">location \/<\/code>:<\/p>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">location \/ {\n    proxy_pass http:\/\/127.0.0.1:8188;\n    ...\n    # X\u00d3A HO\u1eb6C COMMENT D\u00d2NG D\u01af\u1edaI \u0110\u00c2Y:\n    # add_header Cache-Control no-cache;\n}<\/code><\/pre>\n<p>Then save and <strong>Restart Nginx<\/strong> (Restart Nginx).<\/p>\n<h3>Step 2: Disable the OpenLiteSpeed Cache Module (when using Cloudflare Page Cache)<\/h3>\n<p>If you are using plugins such as <i>Super Page Cache for Cloudflare<\/i> to manage caching on Cloudflare and local disk, disable the OpenLiteSpeed cache module to avoid conflicts.<\/p>\n<p>Open the main OpenLiteSpeed configuration file (<code data-no-translation=\"\">httpd_config.conf<\/code>) through the aaPanel interface, find the block <code data-no-translation=\"\">module cache<\/code> and change:<\/p>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">module cache {\n    ls_enabled          0 # \u0110\u1ed5i t\u1eeb 1 th\u00e0nh 0 \u0111\u1ec3 t\u1eaft module\n    ...\n}<\/code><\/pre>\n<p>Save and <strong>Restart OpenLiteSpeed<\/strong>.<\/p>\n<h2>4. Results after the fix<\/h2>\n<p>After completing these two steps, run the check command again. You will see only one header remaining <code data-no-translation=\"\">Cache-Control<\/code> valid from WordPress\/LiteSpeed, and Cloudflare will return the status <strong>HIT<\/strong> immediately on subsequent visits.<\/p>","protected":false},"excerpt":{"rendered":"<p>Detailed guide on how to diagnose and fix Cloudflare cache failure (always returning REVALIDATED or EXPIRED status) due to duplicate Cache-Control headers with no-cache from the origin server using an Nginx Reverse Proxy combined with OpenLiteSpeed model.<\/p>","protected":false},"author":0,"featured_media":39301,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1932,1933],"tags":[1560],"class_list":["post-39300","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-system-admin","category-tech","tag-cloudflare"],"acf":[],"rankmath_keywords":{"primary":"cloudflare cache, openlitespeed, nginx reverse proxy, cache-control no-cache, aapanel","secondary":["openlitespeed","nginx reverse proxy","cache-control no-cache","aapanel"]},"yoast_keywords":{"primary":"","secondary":[]},"yoast_focuskw":"","rankmath_focuskw":"cloudflare cache, openlitespeed, nginx reverse proxy, cache-control no-cache, aapanel","seo_keywords":{"primary":"cloudflare cache, openlitespeed, nginx reverse proxy, cache-control no-cache, aapanel","secondary":["openlitespeed","nginx reverse proxy","cache-control no-cache","aapanel"]},"_links":{"self":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/posts\/39300","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/comments?post=39300"}],"version-history":[{"count":0,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/posts\/39300\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/media\/39301"}],"wp:attachment":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/media?parent=39300"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/categories?post=39300"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/tags?post=39300"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}