The website worked. Mostly.

Visitors could read it. I could publish articles. And if I performed a few familiar rituals in the correct order, I could usually get everything else done.

Publish first. Complete the security check. Upload the image afterward.

Try to change the homepage’s metadata in Divi, however, and I got a spinning wheel that appeared willing to outlive me.

I had learned to work around it.

This is one of the quieter ways a website becomes difficult to maintain: its owner gets good at accommodating things that should be investigated.

I was becoming exceptionally accommodating.

A fresh browser, an older website

There was another symptom. Logged into WordPress, I saw my current content. Open the website in an incognito window, and the sidebar could show a different collection of articles.

I had deliberately adjusted publication dates to arrange those articles. The public sidebar had apparently developed its own editorial policy.

Rather than relying on my recollection, we established a reference: a screenshot showing the correct order. Then we compared it with the logged-out version.

The difference was real.

Checking the public homepage’s response headers gave us something more useful than “the cache is being weird.” Cloudflare was serving a cached copy approximately 3.8 days old. A request that bypassed that cache returned the intended sidebar.

After purging the homepage cache, ordinary public requests returned the correct order too.

That resolved the immediate mismatch. It did not explain why the cache had failed to refresh automatically, and it did not explain Divi’s spinner.

One symptom had evidence behind it. The other still needed investigation.

My small museum of tracking code

Inside Divi’s Integration settings, we found manually embedded Google Analytics scripts.

Two blocks of them.

I also had Google Site Kit installed.

Apparently, I had been curating a small museum of website instrumentation, with no clear retirement policy for the exhibits.

Leaving old integration code in place was maintenance I had deferred. I had not checked whether those blocks were still needed or how they related to the plugin already installed.

That deserved some affectionate ridicule. It also deserved a more careful diagnosis than “old scripts found; case closed.”

Finding something unnecessary does not establish that it caused every problem nearby.

What the save request actually showed

Chrome’s Network panel captured the important failure.

Divi submitted a background request to save the WordPress settings. The response was 403 Forbidden.

The spinner was the visible symptom. The rejected request was the actionable evidence.

That response included a Cloudflare Ray ID, a reference we could use to locate the corresponding request in its security events. Matching the two showed that a managed firewall rule had blocked the settings save.

The manually embedded scripts were a strong suspect: a legitimate settings submission can contain code that a firewall classifies as suspicious. That possibility needed testing rather than an assumption that the security control was wrong.

But the next test mattered.

We removed the Google scripts from the form, preserved the separate verification tag, and tried saving again.

The save still failed.

A later security event showed that another managed firewall check had challenged the cleaned settings submission. Removing the scripts alone had not resolved the problem.

My little tracking-code museum needed clearing out, but it was not a complete explanation.

A narrow fix, followed by a real check

After identifying the additional check affecting the legitimate settings submission, we made a narrowly scoped firewall adjustment for that operation. The other protections remained active.

Then we repeated the work.

The cleaned Integration settings saved. Reloading the page confirmed that the manual Google scripts stayed removed. A subsequent save from the homepage SEO panel completed, and the spinner cleared.

Those checks established more than the disappearance of an animation. They showed that the intended change persisted and that the previously failing save operation could complete. As with HTTP success, interface success, and task success, the visible signal and the completed outcome needed to be distinguished.

The adjustment also has conditions that need to remain part of the site’s maintenance record. A change that works under today’s conditions may need review when those conditions change.

A working fix can still have a boundary worth documenting. Changed conditions can require a new check; yesterday’s successful test does not establish that every future connection will behave identically.

The cache could listen, but it could not clear

That still left the stale public pages. Manually clearing the cache made an individual update visible, but I did not want cache maintenance to become another ritual in the publishing process.

So we traced what should happen after an article changes: WordPress saves the update, its Cloudflare plugin requests a cache purge, and the next visitor receives a fresh copy.

The plugin was installed. It was connected. Cloudflare’s Automatic Platform Optimization was enabled. Those facts made the arrangement look more complete than it was.

A controlled update remained absent from the ordinary public response through roughly 39 seconds of checks. When we asked the WordPress plugin to purge that article directly, it returned “Unauthorized.”

The API token saved in WordPress was valid and active, but it had read permissions without the Cache Purge permission. It could read Cloudflare’s settings; it could not request the cache clearing we expected after an edit. The separate Cloudflare app connection we had used for successful manual purges had different permissions.

I had acquired a connected plugin and mentally promoted it to a functioning publishing integration. Apparently, my museum also had a department of optimistic assumptions.

With my approval, we added the missing Cache Purge permission to the existing token, scoped to this site. That granted the operation needed for publishing updates without extending it to the other websites.

Then we tested the behavior rather than treating the saved permission as the finished result:

  1. We added a temporary, invisible HTML comment to this article and saved the update through WordPress.
  2. A fresh logged-out request to the ordinary article URL received the updated content in about four seconds. Cloudflare reported a cache miss and fetched the fresh page. We had not manually purged it.
  3. We restored the original article. Another logged-out request confirmed the comment was gone in about one second, again without a manual purge.

Those timings describe the two checks we observed, not a promised delivery time for every future edit. What mattered was that both changes passed through the normal update path and invalidated the cached article.

We cleared the remaining old site cache once to remove the backlog, then checked the homepage, glossary, and corrected Decision Context article. Their current content was visible publicly.

The cache mismatch and the Divi save failure had different immediate causes. One involved a missing purge permission; the other involved firewall rules rejecting the settings save. Keeping those findings separate let us fix both without pretending that removing old scripts explained everything.

This was also a practical example of access, capability, permission, authority, and responsibility meeting in one small publishing workflow. The connection existed. The missing permission still had to be identified, deliberately granted, and tested.

What I should have done sooner

I should have reviewed the old integration code.

I should have questioned the publish-first, security-check-second ritual instead of promoting it to standard operating procedure.

And I should have treated the difference between my logged-in view and the public website as something to verify, rather than another minor oddity to remember.

None of that required me to predict the exact firewall rule in advance. It required me to stop accepting the workaround as the explanation.

The useful workflow was straightforward: establish the expected result, reproduce the failure, inspect the request, connect it to the relevant log, make a limited change, and verify what persisted.

If this account becomes part of someone else’s working context, that reasoning is the useful part to carry forward. The observations explain why these changes were appropriate here; they do not establish that a similar-looking failure elsewhere has the same cause.

A rejected save calls for investigation. Depending on the evidence, the appropriate response might be correcting the submission, fixing an integration, or narrowly adjusting a security control. The result to verify is that the legitimate work succeeds while the protections still serve their intended purpose.

That separation between captured state and live state mattered throughout: the screenshot established a reference, the fresh request tested the public response, and the reload checked whether the save had actually persisted.

My contribution was an unusually well-maintained collection of symptoms.

Eventually, we gave them an investigation.