DEV Community

Cover image for How to Give an AI Agent CMS Write Access Without Melting the Cache
Umesh Malik
Umesh Malik

Posted on Originally published at umesh-malik.com

How to Give an AI Agent CMS Write Access Without Melting the Cache

TL;DR AI agent CMS write access is becoming ordinary — an MCP server that lets an agent create, edit, and publish content directly — and the part that breaks first is never the permission check, it's the cache. Cloudflare's own blog runs on a CMS called EmDash that exposes exactly this kind of write access through MCP, sits behind a cache serving 99.5% of static files and 70% of all requests, and absorbed a 28,000 RPS DDoS attack the same month without a noticeable hiccup. The reusable part isn't the vendor — it's invalidating on write instead of on a timer, splitting the object cache from the edge cache, and pooling the database behind both.

Every MCP server that ships a publish_post tool is one bad assumption away from telling an agent its write succeeded while a reader three hops away still sees the old page. Cloudflare's engineering team described exactly this setup when they moved their own blog onto a new CMS called EmDash in August 2026 — a platform built to serve both human editors and AI agents through the same publishing surface, sitting on top of a caching stack tuned for a blog that spikes from 75 requests per second to over 5,000. The interesting part isn't that it works most of the time. It's what had to be true for it to survive a 28,000 RPS DDoS attack on August 10th without anyone downstream noticing.

What is AI agent CMS write access, and why does it usually break the cache?

AI agent CMS write access means a content management system accepts create, edit, publish, and unpublish operations from an AI agent through a tool-calling interface, instead of reserving those actions for a human clicking buttons in an admin panel. EmDash's public-facing MCP server currently exposes four read tools — search_posts, list_posts, get_post, list_tags — and a separate authenticated surface lets authors "browse, create, and edit content, publish and schedule posts, remove files" through the same MCP interface.

The reason this breaks caches specifically, and not just permission models, is that a CMS behind any serious traffic almost always caches its rendered pages. A human editor publishing through an admin UI usually triggers a purpose-built invalidation call, because someone wrote that code path deliberately. An agent calling a generic publish tool is easy to wire up without anyone re-checking that the same invalidation fires — the tool call succeeds, the database row updates, and the cached page in front of it just sits there until a TTL expires. Nobody lied to the agent. The cache just never got the memo.

Why AI agents publishing content is now a caching problem, not a permissions problem

Most of the industry conversation about giving agents write access is about authorization — which tool, which risk tier, who approved the call. That conversation matters, but it treats "the write succeeded" as the end of the story. For a cached CMS it's the middle. A write that updates the source of truth but leaves a cached copy stale is functionally indistinguishable, to a reader, from a write that silently failed — except now your monitoring says everything is fine, because the database is correct.

This is exactly the shape of problem that shows up once agents stop only reading and start acting: the failure mode moves from "the agent did something it shouldn't have" to "the agent did the right thing and the surrounding system didn't propagate it." EmDash is a useful case study precisely because it's a production system, at real traffic, that had to solve the caching half and the agent-tooling half at the same time — not a demo where cache correctness was never load-tested.

The layered cache architecture that survived a 28,000 RPS DDoS

Cloudflare's blog normally sits around 75 requests per second, with organic spikes past 5,000 RPS. On August 10th, it also absorbed a 28,000 RPS DDoS attack — roughly 373 times the baseline load — with no noticeable issue, entirely because of Cloudflare's built-in DDoS protection sitting in front of a cache architecture that was already carrying nearly all of that traffic without touching the database.

A bar chart comparing three real traffic levels for the Cloudflare blog on a log scale: 75 requests per second baseline, over 5,000 requests per second at organic peak, and 28,000 requests per second during the August 10 DDoS attack that the cache architecture absorbed without incident

That headroom comes from three cache layers stacked in front of the database, not one:

  1. Workers Cache, the edge HTTP cache in front of every request, serving 99.5% of static files straight from the edge with no origin round-trip.
  2. An EmDash object cache built on Workers KV, sitting behind the edge cache for the requests that aren't plain static assets — the layer that gets EmDash to 70% of all requests served from cache overall.
  3. Hyperdrive, Cloudflare's connection-pooling layer in front of a PlanetScale database, so the roughly 30% of requests that do miss both cache layers hit a bounded pool of warm connections instead of opening a fresh one apiece.

The layered cache path for a request against EmDash: request arrives at Workers Cache which resolves 99.5 percent of static file requests directly, the remainder falls through to the EmDash object cache on Workers KV which brings the overall cache hit rate to 70 percent, and only the remaining requests reach Hyperdrive's pooled connections into PlanetScale

Rolling this out wasn't a flag flip either: Cloudflare shipped the new platform at 1% of production traffic, then stepped to 5%, 15%, and 100% over the course of a single launch day, watching cache hit rate and error rate at each stage before widening the rollout. That ramp, not just the architecture underneath it, is what turned a full platform migration into a non-event.

Architecture What breaks on an agent publish Cache hit ceiling Load a spike puts on the DB
Edge cache only, TTL expiry Fix goes live in the data, not for readers, until the TTL lapses Capped by content-change frequency Every miss and TTL expiry hits the database
Edge cache + invalidate-on-write Edited page updates fast, but a cache miss still opens a fresh DB connection Higher, bounded by invalidation-key granularity One DB hop per miss, still
Edge + object cache (KV) + invalidate-on-write, DB behind pooled connections Write invalidates both layers before the tool call returns success 99.5% static / 70% overall — EmDash's real numbers Bounded by pool size, not request count

What breaks if you skip cache invalidation in the write path?

The most common failure isn't a security hole — it's a race between the tool response and the cache. An agent calls publish_post, the handler writes the database row, returns success, and the response makes it back to the agent (and to whatever surfaced it to a person) before the old cached page has expired anywhere downstream. Everyone involved believes the write is live. It isn't, for however long the TTL has left to run.

A timeline comparing two invalidation strategies after an agent publish call: the TTL-only path shows a stale page still being served to readers for the remainder of the cache TTL after the write returns success, while the invalidate-on-write path shows the cache purged in the same request before the tool call returns, closing the stale window to zero

Layering more cache in front of that gap makes it worse, not better — every additional cache tier is one more place the same stale copy can be sitting. The fix isn't a faster TTL; it's moving invalidation into the write path itself, so the tool call can't report success until every cache layer it touched has actually been told.

The pattern to copy: giving agents CMS write access without melting the cache

  1. Scope the MCP surface by read/write, not by feature. EmDash's public server exposes only search_posts, list_posts, get_post, and list_tags — pure reads. Publishing, editing, and scheduling sit on a separate, authenticated surface an agent reaches only with author-level credentials — the same split argued for generally in how to build a production MCP server.

  2. Put invalidation inside the write handler, not a cron sweep. The tool call that performs the write is also the tool call responsible for busting every cache layer that could be holding the old version — a publish_post response that returns before invalidation finishes is a response that's lying about what's live.

  3. Split the object cache from the edge cache. EmDash's Workers KV object cache and its edge Workers Cache are two separate layers precisely so an invalidation at one granularity — a specific post, say — doesn't require blowing away everything the edge is holding.

  4. Pool the database connections behind both cache layers. A spike in cache misses, whether from a real traffic surge or an agent doing something unexpected, turns into queued requests against a bounded pool instead of one new database connection per request.

  5. Roll out agent write volume the way you'd roll out the platform underneath it. Cloudflare didn't send 100% of traffic to EmDash on day one; it went 1% → 5% → 15% → 100%, watching hit rate and errors at each step. Ramp the number of agent-initiated writes the same way before trusting it at full volume.

If you're already thinking about MCP tool safety in terms of risk tiers and server-side policy gates, this is the same instinct applied one layer down — the gate that stops a write from happening is necessary, but a write that's allowed still needs a cache that knows about it. And if agents are triggering enough write volume that approval fatigue becomes the real bottleneck, the cache architecture above is what keeps the system correct once you've decided to let more writes through automatically.

If you're standing up the MCP server itself rather than adding write tools to an existing one, deploying it on Cloudflare Workers puts it on the same edge the cache layers above already live on. Scoping OAuth so a client only ever requests the write scopes it needs closes the remaining gap: having a write tool is not the same as being allowed to call it right now.

For the rest of this cluster, see MCP Servers; for the AI Gateway layer that logs and caches the model calls sitting behind an agent's tool use in the first place, see AI Gateway for Workers AI.

FAQ

What is AI agent CMS write access?
It is a content management system accepting create, edit, publish, and unpublish operations from an AI agent through a tool-calling interface such as MCP, instead of reserving those actions for a human in an admin panel. The agent calls a tool like publish_post the way a human clicks Publish, and the CMS has to treat that call as a real write with real caching consequences.

Why does invalidate-on-write matter more than a fast cache?
A fast cache with no invalidation path just serves stale content quickly. The moment a write happens, every cache layer holding the old version has to be told before the write is genuinely done, or the CMS reports success on a change readers can't yet see. Speed and correctness are separate problems, and only one is solved by adding more cache.

Do I need Hyperdrive and PlanetScale specifically to do this?
No — those are Cloudflare's and EmDash's specific choices. The transferable idea is pooling database connections behind a layer the edge talks to, so a spike in cache misses becomes queued requests against a bounded pool instead of one new connection per miss. Any connection pooler in front of your database gets you the same property.

What MCP tools should a CMS expose to an agent?
Split reads from writes and scope each narrowly. EmDash's public MCP server exposes only search_posts, list_posts, get_post, and list_tags — read-only lookups — while create, edit, publish, and remove sit behind a separate, authenticated author-facing surface.

How do I roll out agent write access without risking an outage?
Behind a traffic percentage, not a flag flipped to 100%. Cloudflare's migration to EmDash went live at 1% of production traffic, then stepped to 5%, 15%, and full rollout only after each stage held, with cache hit rate and error rate as the abort signal at every step. Apply the same ramp to agent write volume.

Does a layered cache eliminate the risk of an agent publishing something wrong?
No. A layered, invalidate-on-write cache guarantees that whatever the agent published becomes visible correctly and fast — it says nothing about whether the content should have been published. That's a separate problem, best handled with the same write-tool risk tiering you'd put in front of any agent action with real-world blast radius.

Sources


Written for umesh-malik.com — no-fluff technical writing on AI, Web Dev, and Engineering.


Originally published at umesh-malik.com

Keep reading on umesh-malik.com:

Top comments (0)