{"id":11115,"date":"2026-10-01T13:56:14","date_gmt":"2026-10-01T13:56:14","guid":{"rendered":"https:\/\/schindlerengineering.com\/public\/?p=11115"},"modified":"2026-10-01T13:56:14","modified_gmt":"2026-10-01T13:56:14","slug":"the-flush-was-telling-the-truth","status":"publish","type":"post","link":"https:\/\/schindlerengineering.com\/public\/2026\/10\/01\/the-flush-was-telling-the-truth\/","title":{"rendered":"The flush was telling the truth"},"content":{"rendered":"<p>A post went live. The permalink worked. The front page &mdash; the URL people<br \/>\nactually type &mdash; showed no sign of it for two hours.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/schindlerengineering.com\/public\/wp-content\/uploads\/2026\/10\/cache-timeline.png\" alt=\"Two hours, three theories\" style=\"max-width:100%;height:auto\" \/><\/p>\n<p>Two of those three theories were about software we control, and both were<br \/>\ndocumented in our own code from previous incidents. A known bug is the most<br \/>\nseductive wrong answer there is: it explains the symptom, it comes with a<br \/>\ncitation, and it stops you looking.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/schindlerengineering.com\/public\/wp-content\/uploads\/2026\/10\/cache-evidence.png\" alt=\"What the plugin reported next to what the wire reported\" style=\"max-width:100%;height:auto\" \/><\/p>\n<p>The cache flush reported success every single time, and it was<br \/>\n<strong>telling the truth<\/strong> &mdash; about the layer it owns. W3TC really<br \/>\nwas empty. The request simply never reached it, because the host runs an nginx<br \/>\nproxy cache in front of WordPress with a two-hour TTL.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/schindlerengineering.com\/public\/wp-content\/uploads\/2026\/10\/cache-layers.png\" alt=\"Three cache layers and what each flush actually reaches\" style=\"max-width:100%;height:auto\" \/><\/p>\n<p>Nothing inside WordPress can see that layer, let alone clear it. But the<br \/>\nproxy accepts a purge:<\/p>\n<pre>curl -X PURGE https:\/\/example.com\/   -&gt;   204<\/pre>\n<p>The pipeline now runs <strong>flush WordPress &rarr; purge the proxy &rarr;<br \/>\nwarm the front doors<\/strong>, in that order. Warming before purging just<br \/>\nre-cements what the proxy is already holding.<\/p>\n<h2>The one sentence<\/h2>\n<p><strong>When a flush succeeds and the page is still wrong, you are flushing<br \/>\nthe wrong cache.<\/strong><\/p>\n<p>A flush can only report on the layer it owns. The response headers are a<br \/>\nreceipt from every layer that touched the request &mdash;<br \/>\n<code>X-Proxy-Cache<\/code>, <code>Age<\/code>, <code>Via<\/code>,<br \/>\n<code>X-Cache<\/code>, <code>CF-Cache-Status<\/code>. We theorised for two hours<br \/>\nabout our own code; the answer was one <code>curl -I<\/code> away, in software we<br \/>\ndid not know was there.<\/p>\n<p>Read the headers first. They do not have a theory.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A post went live. The permalink worked. The front page &mdash; the URL people actually type &mdash; showed no sign of it for two hours. Two of those three theories were about software we control, and both were documented in our own code from previous incidents. A known bug is the most seductive wrong answer &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/schindlerengineering.com\/public\/2026\/10\/01\/the-flush-was-telling-the-truth\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;The flush was telling the truth&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","footnotes":""},"categories":[1],"tags":[],"class_list":["post-11115","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/schindlerengineering.com\/public\/wp-json\/wp\/v2\/posts\/11115","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/schindlerengineering.com\/public\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/schindlerengineering.com\/public\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/schindlerengineering.com\/public\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/schindlerengineering.com\/public\/wp-json\/wp\/v2\/comments?post=11115"}],"version-history":[{"count":1,"href":"https:\/\/schindlerengineering.com\/public\/wp-json\/wp\/v2\/posts\/11115\/revisions"}],"predecessor-version":[{"id":11116,"href":"https:\/\/schindlerengineering.com\/public\/wp-json\/wp\/v2\/posts\/11115\/revisions\/11116"}],"wp:attachment":[{"href":"https:\/\/schindlerengineering.com\/public\/wp-json\/wp\/v2\/media?parent=11115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/schindlerengineering.com\/public\/wp-json\/wp\/v2\/categories?post=11115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/schindlerengineering.com\/public\/wp-json\/wp\/v2\/tags?post=11115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}