Skip to content
BlogAgents10 min read

Preview isolation stops at the binding

Cloudflare's roadmap says a Preview's service binding still calls production, and previews can't consume their own queues. So the agent's green means less.

Most of what I write here is about the parts of agent verification you own: the approval gate, the tool allow-list, the dry-run path. Cloudflare's Worker Previews, announced today, are the part you do not own — the environment your agent deploys into and then checks itself against. That makes it worth reading the announcement the way I would read a contract, which is to say from the end.

The feature itself is good and the design is right. npx wrangler preview gives a branch its own URL, its own variables and secrets, its own bindings, its own observability, and its own state, and the page describes the loop it was built for plainly: an agent deploys, opens the URL with Playwright MCP, clicks through, queries traces through the Workers Observability MCP server, patches, redeploys, and verifies. "Every iteration stays scoped to the branch."

That is the promise, and it is a real improvement on what came before. The page is honest that the old preview URLs were weaker — "We're now calling those Version URLs because they point to specific uploaded Worker versions", and they "don't create an isolated environment for each branch and could only point to production resources." Previews fix the state layer and the config layer.

Then there is the section at the end, and it is the reason I am writing this rather than just linking the announcement.

Three sentences in "What's next"

The page's roadmap lists three gaps it intends to close. Read as a description of what is true today, they are a map of where an agent's verification is not hermetic:

  • "Today, a service binding from a Preview still calls the bound Worker's production deployment." The stated goal is "keeping the entire request path inside matching Previews" — which is a way of saying the request path is not entirely inside matching Previews.
  • "Previews can send messages to Queues but cannot consume them", and "isolating Workflow executions requires separate configuration." The goal is "the entire asynchronous flow scoped to the branch automatically" — so today, the asynchronous flow is not.
  • "Support long-lived Previews for staging and QA", because "not every branch is short-lived."

An environment that can reach production is not a test environment. It is a production environment with a different URL, and the difference is exactly the part the agent cannot see.

The queue gap is the one that costs you

The service-binding gap is easy to picture: the agent's change calls a service it no longer controls, and the call lands in production. Ugly, but at least it is a synchronous failure you might catch in a log.

The queue gap is worse, because it is silent on both sides. Walk the loop.

Your agent changes the code that enqueues a job. It deploys to a Preview, opens the URL, clicks the button, and the Preview enqueues a message. The page tells you the Preview can send. It also tells you the Preview cannot consume. So the message lands on the production queue and the production consumer picks it up — that is the only consumer that exists.

Now the agent goes to check its work, which is the thing the page was built to let it do. It queries traces through the Observability MCP server, and the page promises that "every Workers Observability tool you're already used to is available, scoped to each individual Preview." Scoped to the Preview. The job that just ran did not run in the Preview. It ran in production, and its traces are in production's observability, which the agent is not looking at.

So the agent sees a message sent and nothing consumed. That admits two readings — the change works and the evidence is elsewhere, or the change broke the consumer — and the agent has no way to tell them apart from inside the environment it was given. The rational response to an ambiguous verification signal is to gather more evidence. Which means more turns, more screenshots, more trace queries, and then a patch and another deploy.

This is the part that connects to your bill rather than your architecture.

What an inconclusive check costs

A browser-driving agent re-sends its whole transcript every turn, so the input tokens a verification loop bills are quadratic in the number of turns, not linear. Take a stated shape: a stable prefix of tool definitions and branch config at 9,000 tokens, and 19,400 tokens appended per turn — a 1280×800 screenshot at roughly 1,400 image tokens, a 6,000-token DOM snapshot, and 12,000 tokens of trace JSON. Turn k bills a context of 9,000 + (k−1) × 19,400, so over N turns the total is:

input tokens  =  N × 9,000  +  19,400 × N(N−1)/2

N = 8     72,000 + 543,200  =    615,200
N = 16   144,000 + 2,328,000 =  2,472,000

Doubling the loop from 8 turns to 16 multiplies billed input by 4.02×. Not 2×. The transcript is the thing being re-read, and a longer transcript is re-read more times.

Price it at Claude Sonnet 5 rates checked today — $2/MTok input, $0.20/MTok cache read, $10/MTok output — with the stable prefix cached and the growth priced at full input, which is the conservative case:

                                    N = 8          N = 16
prefix, cache read   72,000 / 144,000 × $0.20   $0.01440      $0.02880
growth, input       543,200 / 2,328,000 × $2    $1.08640      $4.65600
output              4,800 / 9,600 × $10         $0.04800      $0.09600
                                                --------      --------
                                                $1.14880      $4.78080

A loop that terminates in 8 turns costs about $1.15 per check. A loop that runs to 16 because the signal stayed ambiguous costs $4.78 — 4.16× for twice the length. At 30 changes a day, an agent whose verification terminates costs $1,033.92 a month. Have half of those checks run long because a preview cannot see its own queue, and the same work costs $2,668.32. The gap is $1,634.40 a month, and nothing about it appears anywhere except the token counters.

That is the real cost of a non-hermetic test. It is not that it occasionally lies. It is that an ambiguous signal is the most expensive signal there is, because the correct response to ambiguity is to spend more, and the spend buys information the environment structurally cannot provide.

Previews are also a line item now

The second thing the roadmap sentence about long-lived previews implies is arithmetic. Each preview gets its own state, and the page says Cloudflare "automatically creates a new Durable Object namespace and Container application for that Preview", with "hundreds of Previews at the same time" supported.

Durable Objects hibernate when idle, so a quiet preview is close to free on that line. Containers are different — Cloudflare publishes $0.0000025 per GiB-second of memory, $0.000020 per vCPU-second, against 25 GiB-hours and 375 vCPU-minutes included per month. Take one long-lived preview holding a container warm at 1 GiB and half a vCPU for a 30-day month:

seconds            30 × 86,400                 =  2,592,000
memory GiB-s       1 × 2,592,000               =  2,592,000
  included         25 GiB-h × 3,600            =     90,000
  overage          2,502,000 × $0.0000025      =     $6.255
vCPU-s             0.5 × 2,592,000             =  1,296,000
  included         375 vCPU-min × 60           =     22,500
  overage          1,273,500 × $0.000020       =    $25.470
                                                  --------
                                                   $31.725  per preview / month

$31.73 per warm preview per month, and 100 of them is $3,172.50 a month. More to the point: a single one of those previews burns 28.8× the account's entire included container memory and 57.6× its included vCPU allowance. The allowance is sized for roughly one warm container, and the product is designed for hundreds of environments. That is not a criticism — metered overage is how usage-based pricing works — but if you are pointing an agent at a preview per iteration, the previews are now a line item with the same shape as the tokens.

What I would actually change

Three things, none of them exotic.

Make the allowed bindings part of the code review, exactly like the tool allow-list you already put in front of an agent. If a branch cannot call production, the config that says so should be visible in the diff, not inferred from a roadmap note.

Assert on the producer, not the consumer. The agent can verify that a message with the right payload and the right key reached the queue without needing the consumer to run at all — that is a check that works inside the environment you have. Waiting for an effect that only production can produce is how a verification loop stops terminating. This is the same discipline as retry is not resume: know which layer you are asserting on before you spend a retry on it.

Record the verification loop as a cost centre per change, the way attributing model spend does. A loop length that creeps from 8 to 16 is a 4.16× cost event and it will not show up in a daily total.

What I am not taking from this

The page publishes no pricing, no TTL, and no per-preview concurrency cap. The only scale figure is "hundreds of Previews at the same time" and the only availability line is "Worker Previews are available now." It does not say whether a preview holds a container warm, so the $31.73 is my scenario, not their number — substitute your own sizing and the ratio to the included allowance holds while the dollars move.

Two things make me believe the roadmap sentences rather than read them as hedging. The isolation that does exist is real and specific: a per-preview Durable Object namespace and Container application, created automatically so a failed migration or schema change stays contained, which is the part I would have expected to be hardest. And the page names its own gaps in the same document that ships the feature, with the future state spelled out next to the current one. A vendor that writes down "still calls production" is telling you something a vendor that writes "isolated environments" is not.

What I am taking from it is narrower than the announcement. Preview environments close the state problem. They do not yet close the call problem or the async problem, and those are precisely the two edges an agent reaches for when it goes looking for evidence that its change worked.


An agent verifying itself against an environment that reaches production is the kind of thing an AI reliability audit is supposed to find before it becomes an incident, and it sits squarely in the agent integration work I do most weeks. If the loop length is already creeping, what an AI feature costs to build and LLM API costs out of control are the next two pages.

All Cloudflare facts and quotations — npx wrangler preview, the Version URL distinction, the per-preview Durable Object namespace and Container application, "hundreds of Previews at the same time", the per-preview observability scoping, the Playwright and Workers Observability MCP loop, "Every iteration stays scoped to the branch", and the three roadmap items quoted above — are from blog.cloudflare.com/worker-previews, published 2026-09-22 by Yomna Shousha, read the same day. Container, Durable Object and Workers prices are from developers.cloudflare.com/workers/platform/pricing, and model rates from claude.com/pricing, both checked 2026-09-22. The 9,000-token prefix, the 19,400-token per-turn growth, the 600-token output, the 8-and-16-turn loop lengths, the 30-changes-a-day volume and the 1 GiB / 0.5 vCPU warm container are my stated scenario, not measurements.

Something here

the audit is the cheapest way to find out for certain.