Cloudflare Worker Previews for Safer Coding Agents

Published on 9/23/2026By Prakhar Bhatia
Cloudflare Worker Previews for Safer Coding Agents

A coding agent can open a pull request in minutes. The harder question is where its code should run before a person approves it. A shared staging Worker gives every branch the same URL, bindings, logs, and mutable state. Two agents working at once can overwrite one another. A test that succeeds may have exercised the wrong commit. A cleanup step can remove data another review still needs.

Cloudflare Worker Previews give each branch or pull request a named environment under the same Worker. The environment gets a stable preview URL, immutable deployment URLs, separate configuration, and its own observability stream. Durable Objects and Containers are isolated automatically. Other stateful bindings need deliberate separation.

That combination makes previews useful for agent-generated changes, but a preview is not a security policy by itself. The safe design has five parts: a unique name, least-privilege deployment credentials, explicit non-production bindings, access control on the URL, and reliable cleanup.

What Worker Previews change

Cloudflare introduced Worker Previews on September 22, 2026. The feature is designed for branch and pull-request testing in the same runtime that serves the production Worker. A team can create hundreds of named previews without creating a separately managed Worker for every short-lived change.

Each named preview has two useful addresses:

  • A stable preview URL that follows the latest deployment to that preview name.
  • An immutable deployment URL that points to one exact deployment.

The stable URL is convenient for a pull request comment, a human review, or a browser-based test suite. The immutable URL is better evidence. If an agent reports that deployment abc123 passed, reviewers can open that exact build instead of whatever was most recently pushed to the branch.

Cloudflare currently documents 100 previews per Worker on the Free plan and 500 on paid plans. Each preview retains up to 100 deployments, with older deployments removed as the limit is reached. These are generous limits for ordinary pull-request traffic, but repositories with automated dependency updates or large agent swarms still need cleanup.

Why a shared staging Worker breaks under agent concurrency

Traditional staging often assumes a small number of human developers who coordinate releases. Coding agents change that operating model. Several tasks can start from the same commit, make unrelated changes, and deploy within the same few minutes.

On a shared staging Worker, the last deployment wins. The first agent may run an API test after the second agent has replaced the code. Logs from both tasks are interleaved. A database migration from one branch can change the assumptions of another. Review links become time-sensitive because they no longer identify a commit.

A named preview removes the code collision. It also gives the team a natural unit for authorization, observability, and deletion. The branch agent/rate-limit-fix can map to a sanitized preview name such as pr-1842. Everything produced for that review can be labeled with the same identifier.

This fits the same principle we use in agentic CI pipelines: an agent should produce inspectable evidence in a bounded environment, not merely assert that its patch works.

A practical lifecycle for an agent-created preview

A robust lifecycle is short and deterministic:

  1. CI receives a pull-request event from a trusted repository context.
  2. The workflow creates a preview name from the pull-request number, not raw branch text.
  3. It deploys with wrangler preview and captures the JSON result.
  4. Tests run against the immutable deployment URL.
  5. The stable preview URL is posted to the pull request for review.
  6. Logs, test results, and the deployment identifier are attached to the check.
  7. The preview is deleted when the pull request closes.

The pull-request number is a better identifier than a branch name because it is compact, stable, and easy to validate. It also avoids punctuation that may be unsuitable in resource names.

Cloudflare requires Wrangler 4.135.0 or later for Worker Previews. A minimal local deployment looks like this:

npx wrangler preview --name pr-1842 --json

The JSON output is important. Parse it and pass the URLs to later steps. Do not scrape terminal prose or guess a hostname.

Configure preview values explicitly

Preview deployments do not automatically inherit production settings. That is a useful safety property because a branch cannot silently acquire every production binding, route, and secret. It also means a preview that is not configured carefully may fail only after deployment.

Keep shared runtime settings at the top level and preview-specific values under previews:

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "orders-api",
  "main": "src/index.ts",
  "compatibility_date": "2026-09-23",
  "vars": {
    "APP_ENV": "production"
  },
  "previews": {
    "vars": {
      "APP_ENV": "preview",
      "ALLOW_TEST_USERS": "true"
    }
  }
}

Cloudflare keeps items such as compatibility_date and static asset configuration at the top level. Production routes, Cron Triggers, and queue consumers are not placed in the preview block. Treat configuration review as part of the pull request, especially when an agent modifies bindings or compatibility flags.

Secrets deserve a separate path. Use preview secrets for credentials that are valid only in preview infrastructure. A production API token copied into preview configuration defeats the main containment benefit.

Understand the resource isolation matrix

Worker code isolation and data isolation are different things. According to Cloudflare's preview resource documentation, Durable Objects and Containers are automatically isolated for each preview. Many other bindings are not.

ResourceDefault preview behaviorSafer agent setup
Durable ObjectsAutomatically isolatedVerify namespace behavior in integration tests
ContainersAutomatically isolatedApply preview-specific resource limits
KVUses the configured namespaceBind a dedicated test namespace
D1Uses the configured databaseBind a disposable or seeded preview database
R2Uses the configured bucketUse a test bucket and object prefix
HyperdriveUses the configured bindingPoint to a non-production database
VectorizeUses the configured indexCreate a test index or use read-only fixtures
Service bindingsCalls the bound production WorkerReplace with a test service or enforce read-only calls
QueuesProducers are available, consumers are notSend only to a test queue
WorkflowsExisting deployed workflowsAvoid irreversible production actions

The service-binding behavior is the easiest trap to miss. A preview can be isolated at its public URL while an internal call still reaches a production Worker. Map the complete call graph before allowing an agent to run end-to-end tests.

Give the agent a narrow deployment credential

The workflow needs a Cloudflare API token and account identifier. It does not need a broad account token. Cloudflare's GitHub Actions guidance recommends scoped API tokens, and that advice matters more when untrusted or agent-produced code enters the workflow.

Store the token in the repository's secret store. Expose it only to the deployment job. Do not make it available to pull requests from forks, arbitrary shell steps, or the Worker at runtime.

A useful separation is:

  • The coding agent proposes source and configuration changes.
  • A fixed, reviewed CI workflow performs the deployment.
  • A separate job runs tests against the returned URL.
  • The close event invokes a fixed cleanup command.

This keeps the agent from rewriting the mechanism that grants it access. Changes to the deployment workflow should require code-owner review.

Threat-model the pull-request boundary

The most important distinction is whether the pull request comes from a trusted branch in the repository or from a fork. Workflows triggered by forked code should not receive Cloudflare deployment credentials. Even when the contributor is trusted, the code under review can read environment variables, make outbound requests, or change test scripts if the workflow exposes secrets to the same process.

Separate build and deploy responsibilities. A build job can run linters and unit tests with no cloud credential. A protected deploy job can consume the checked-out commit through a fixed command after repository rules approve the event context. Keep the deployment token out of package lifecycle scripts because an agent can modify package.json and turn npm install into a secret-exfiltration step.

Review these attack paths before enabling previews:

  • A modified test script prints environment variables or uploads them to an external host.
  • A Worker deployed for review reads a shared KV, D1, or R2 binding and returns production data.
  • A service binding reaches a privileged production Worker that trusts internal traffic.
  • A preview sends email, messages, payments, or webhooks with live credentials.
  • An attacker guesses a public preview URL and reaches an unreleased admin route.
  • A close-event workflow accepts an unvalidated name and deletes another preview.

Controls should be enforceable outside the proposed code. Repository environment protection, scoped tokens, fixed CI actions, isolated bindings, and network-side access policies are stronger than asking generated code to behave.

Decide what the agent may observe

Coding agents often need logs to diagnose a failing preview. Give them the smallest useful view. A sanitized test log with request identifiers, stack traces, and synthetic fixtures is usually enough. Account-wide logs or production traces can contain customer identifiers, bearer tokens, and internal URLs that are unrelated to the task.

If an agent can query observability data directly, scope access to the named preview and a short time range. Redact authorization headers, cookies, query-string secrets, and request bodies by default. Record when an automated system reads logs and which pull request authorized the access.

There is also a prompt-injection boundary. Data returned by the application, logs, issue text, and pull-request comments are untrusted inputs to an agent. They should not be able to alter the fixed deployment workflow or convince it to reveal a secret. Treat natural-language instructions found in runtime data as data, not as workflow authority.

Build the GitHub Actions workflow

Cloudflare publishes an automation example for pull requests. The following shape adds a few controls that matter for coding agents:

name: worker-preview

on:
  pull_request:
    types: [opened, synchronize, reopened, closed]

permissions:
  contents: read
  pull-requests: write

concurrency:
  group: worker-preview-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  deploy:
    if: github.event.action != 'closed' && github.event.pull_request.head.repo.full_name == github.repository
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm test
      - name: Deploy preview
        run: npx wrangler preview --name pr-${{ github.event.pull_request.number }} --json
        env:
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

Production deployments should remain a different workflow with different permissions. A preview check passing is evidence for review, not permission to promote itself.

Test the immutable deployment, review the stable URL

Use the two URL types for different jobs. The test runner should receive the immutable deployment URL from the deployment result. The pull-request comment should present both the stable URL and the tested deployment identifier.

Start with a small set of tests that establish the environment boundary:

curl --fail --silent --show-error "$DEPLOYMENT_URL/health"
curl --fail --silent --show-error \
  -H "X-Test-Run: $GITHUB_RUN_ID" \
  "$DEPLOYMENT_URL/api/version"

Then run contract and browser tests. Include assertions that expose configuration mistakes, such as the environment name, non-sensitive database marker, and build commit. Never return secrets or full binding details from a debug endpoint.

For agent-generated applications, add adversarial checks. Try a production account identifier. Attempt a write outside the test tenant. Confirm that outbound webhooks resolve to a test receiver. These tests prove containment instead of assuming it.

Protect preview URLs with Cloudflare Access

Preview URLs are public by default. That may be acceptable for a public documentation change, but it is a poor default for admin screens, unreleased product behavior, internal APIs, or data-backed applications.

Cloudflare supports custom preview domains and recommends using a dedicated hostname. A wildcard DNS record and certificate can provide addresses such as pr-1842.preview.example.com. Put Cloudflare Access in front of that hostname and authorize the people or service identities that need to review it.

Access control does not make production data safe. It limits who can reach the preview. You still need separate data bindings, test credentials, and outbound-action controls.

If an automated browser suite must pass Access, give it a narrowly scoped service token. Keep that token in the test job and rotate it independently of the deployment token.

Use preview-specific observability

Cloudflare gives previews separate logs, traces, metrics, and Tail Worker behavior. This is valuable when an agent changes error handling or performance-sensitive code. Reviewers can inspect only the traffic for one branch rather than filter a shared staging stream.

Cloudflare's testing and debugging guide notes that previews can use full sampling. That makes a short-lived environment a good place to collect a complete trace set, provided the logs do not include credentials or personal data.

Useful evidence for a pull request includes:

  • The exact deployment identifier and commit SHA.
  • Test request identifiers that can be found in logs.
  • Error count and sampled trace links.
  • CPU time and subrequest changes for representative calls.
  • A list of bindings used by the preview.

Avoid turning observability into an unbounded data dump. Attach the evidence needed to review the change, then rely on retention policies and preview deletion.

Handle migrations and mutable state separately

Schema changes are where disposable environments become genuinely useful. A preview should not run a migration against the production database. For D1, bind a dedicated database or create a disposable one as part of the workflow. For an external database behind Hyperdrive, use a preview database, schema, or tenant that the preview credential cannot escape.

Seed only the records needed by tests. Synthetic fixtures are safer than a copy of customer data and make failures reproducible. If production-like distribution matters, generate it rather than exporting identities, tokens, or free-form user content.

Make migrations idempotent where practical. A pull request may deploy several times, and CI retries happen. The preview name is stable while deployments beneath it are not.

If the application cannot support isolated state, be honest about the limit. Run read-only smoke tests and reserve mutation tests for a controlled environment. A preview URL cannot compensate for an unsafe database topology.

Make test data disposable and recognizable

Add a preview identifier to every synthetic tenant, object key, and webhook event. This makes accidental cross-environment writes visible and simplifies cleanup. For example, an R2 object path can begin with previews/pr-1842/, while a database tenant can store preview_id = 'pr-1842' under a credential restricted to that tenant.

Do not depend only on naming. Enforce the boundary with database permissions, separate resource identifiers, or both. An application bug can omit a prefix. A credential that cannot write outside the preview schema turns that bug into a failed test instead of a production incident.

Fixtures should be small enough to recreate on every deployment when needed. Version the fixture schema with the application and store no real access tokens, email addresses, or free-form customer text. If a bug requires a production-shaped case, reduce and anonymize it before adding it to the test corpus.

Clean up closed and abandoned previews

Deletion should be triggered by the pull-request close event, but events can fail. Add a scheduled reconciliation job that lists active previews, compares them with open pull requests, and flags or removes stale entries after a grace period.

Cleanup needs to cover resources the preview workflow created outside Worker Previews. That can include a D1 database, R2 prefix, external test tenant, webhook receiver, or Access policy. Label each resource with the pull-request number and creation time.

Use a two-stage policy for anything with diagnostic value:

  1. Disable access and mark the resource expired when the pull request closes.
  2. Delete it after a short retention window unless an incident or review hold exists.

This gives engineers time to inspect a failure without leaving old environments reachable indefinitely.

Know where previews differ from other Cloudflare workflows

Worker Previews are one of three related tools. They solve different problems.

ToolBest fitResource behavior
Worker PreviewsBranch and pull-request testingNamed isolation under one Worker, with resource-specific rules
Version preview URLsInspecting an uploaded production versionUses production resources
Wrangler environmentsPersistent staging, regional, or customer environmentsSeparate named Workers with independent configuration

Use Worker Previews for short-lived review. Use a Wrangler environment when the environment must persist, has a distinct operational owner, or needs fully independent configuration. Use a version preview URL when you are validating the exact version already moving through production deployment controls.

Cloudflare states that long-lived staging support for previews is planned. Until the documented model changes, do not stretch a pull-request primitive into a permanent environment without understanding its limits.

A review checklist for coding-agent previews

Before enabling automatic preview deployment, verify these controls:

  • Wrangler is 4.135.0 or newer and the version is pinned in the lockfile.
  • Preview names come from validated pull-request numbers.
  • Forked pull requests cannot access deployment secrets.
  • The deployment token cannot modify unrelated account resources.
  • Preview variables and secrets are explicit.
  • D1, KV, R2, Hyperdrive, Vectorize, queues, and workflows have reviewed boundaries.
  • Service bindings do not create an unexpected path to production.
  • The test suite targets the immutable deployment URL.
  • Human review uses a stable URL protected by Access when needed.
  • Logs and traces identify the commit without exposing sensitive values.
  • Close-event cleanup and scheduled reconciliation both exist.
  • Production promotion remains a separate, human-governed action.

This design gives coding agents fast feedback while keeping the evidence legible to humans. The same boundary also helps ordinary engineering teams: parallel branches stop fighting over staging, review links remain useful, and the path from commit to observed behavior becomes easier to audit.

Sources and freshness

This guide was verified on September 23, 2026 against Cloudflare's Worker Previews announcement, preview overview, configuration reference, resource isolation table, testing guide, custom-domain guide, automation examples, and workflow comparison. Limits and binding behavior can change, so check the linked references before standardizing the workflow across a large account.


FAQs

What is a Cloudflare Worker Preview?

A Worker Preview is a named, branch-sized deployment environment under one Worker. It has its own URL, configuration, observability, and automatically isolated Durable Objects and Containers.

Are Worker Previews safe for coding agents?

They are a strong execution boundary when paired with scoped credentials, Cloudflare Access, separate stateful resources, explicit cleanup, and tests that prove no preview can write to production data.

Do Worker Previews copy production settings?

No. Preview deployments do not inherit production settings automatically. Define preview bindings and variables explicitly in the previews configuration block.

Which bindings are automatically isolated?

Durable Objects and Containers are automatically isolated per preview. KV, D1, R2, Vectorize, Hyperdrive, Analytics Engine, Pipelines, and several other bindings require separate preview resources if you need data isolation.

Can a preview call another production Worker?

Yes. A service binding from a preview currently calls the bound Worker's production deployment, so teams must treat that boundary as a deliberate production dependency.

How many previews can one Worker have?

Cloudflare documents a limit of 100 previews per Worker on the Free plan and 500 on paid plans, with up to 100 deployments retained per preview.

Should preview URLs be public?

Preview URLs are public by default. Protect sensitive applications with Cloudflare Access and avoid placing secrets or customer data in an unprotected preview.

🚀

Work with us

Let's build something together

We build fast, modern websites and applications using Next.js, React, WordPress, Rust, and more. If you have a project in mind or just want to talk through an idea, we'd love to hear from you.

Related Articles


Live Chat