Feature

A Worker Preview URL does not mean an isolated database

Learn what Worker Previews isolate automatically, how to align D1 bindings and migrations, and where publishing tests can still reach production.

Impetuous · · 4 Min Read

A branch-specific Preview URL does not guarantee a branch-specific database. Two Cloudflare Worker Previews bound to the same D1 database_id share rows. If that ID belongs to production, the Preview is using the production database—not a copy. KV namespaces and R2 buckets follow the same resource-identity rule. Cloudflare’s isolation reference makes this distinction explicit.

For a publishing system, that means a test article edit, import or schema migration can affect live content even though the code runs at a separate URL. The safe boundary is the complete set of resources the Preview can reach, not its hostname.

What is isolated automatically?

Worker Previews provide branch-specific code, configuration, URLs and observability under one Worker. They differ from the older uploaded-version URLs, now called Version URLs, which do not create isolated branch environments. Cloudflare’s announcement describes that distinction.

As of October 3, 2026, the important storage boundaries are:

Resource Preview isolation What to configure
Durable Objects defined in the same Worker, without script_name Automatic namespace and storage per Preview Export the class and declare its migration; add a Preview binding if accessed through env.
Containers Automatic application and instances per Preview Declare container definitions under previews.containers, plus the required SQLite-backed Durable Object setup.
D1 Not automatic Bind each isolated Preview to a different database.
KV Not automatic Use a different namespace ID.
R2 Not automatic Use a different bucket name.
Hyperdrive Not automatic Use a separate configuration pointing to a separate database or schema.

These rules come from the resource binding reference. A different Hyperdrive configuration alone is insufficient if it still reaches the same underlying data. Cloudflare describes Container support in Previews as partial: verify that the process starts and responds before relying on it for testing.

Shared staging is separate from production, but not separate between branches. It is a reasonable proposed default for read-only layout reviews using stable fixtures, provided those review paths really do avoid writes. Use branch-specific storage for schema changes, destructive imports or tests that modify shared state.

Keep the D1 runtime and migration targets together

Preview variables and data bindings belong in the previews block of the Wrangler configuration; they are not inherited from production. Keep the application’s binding name—for example, DB—but point it at the chosen test database. Wrangler uses the configuration from the current branch when running npx wrangler preview. Cloudflare’s configuration guide documents this behavior.

Cloudflare’s documented D1 workflow uses two configuration files:

File Database declaration Purpose
wrangler.jsonc previews.d1_databases Selects the database used by the running Preview.
wrangler.preview-migrations.jsonc Top-level d1_databases Selects the database receiving migrations.

For an isolated branch, choose a separately provisioned test database and set the same database_name and database_id in both declarations. The binding aliases can differ: Cloudflare’s example uses DB for runtime access and PREVIEW_DB for migrations. Both must resolve to the same physical database. Put migration files in migrations/, or set migrations_dir to their location. D1 migration instructions

With PREVIEW_DB declared in the migration configuration, apply migrations before deploying:

npx wrangler d1 migrations apply PREVIEW_DB --remote --config wrangler.preview-migrations.jsonc
npx wrangler preview

The failure to prevent is a split target: Preview code uses the branch database, while the migration command changes shared staging—or production. Add a proposed CI gate that compares the two IDs and rejects production database IDs before any remote migration runs. If several Previews intentionally share one database, coordinate migrations once for that database rather than independently per Preview.

Check paths that can still reach production

Database isolation does not isolate downstream publishing actions. Cloudflare currently documents these limits:

  • Service bindings call the bound Worker’s production deployment, not a matching Preview. A Preview can therefore call a live publishing service. Bind to a dedicated non-production Worker where needed; for same-Worker calls, Cloudflare recommends ctx.exports.
  • Queue producers can send messages, but Previews cannot consume them. A message sent to a production Queue can be handled by production. Use a test Queue with a separately deployed test consumer.
  • Workflow bindings use existing deployed Workflows. Deploy a dedicated non-production Workflow before binding to it.
  • Cron Triggers target production. To test scheduled logic, expose the shared function through a protected, test-only Preview route; this does not validate actual scheduler delivery.

These are current Preview limitations, not automatically isolated capabilities.

Secrets need separate attention. New Previews receive Base secrets at creation; later Base changes do not update existing Previews. Use test credentials and explicitly update active Previews when rotating them. Secret configuration

A proposed release gate for content systems

Before approving a branch, require:

  1. A resource check: runtime and migration targets match, and writable resources are non-production.
  2. An isolation check: create a synthetic article through Preview A, confirm it reaches A’s selected database, and verify it is absent from the separately selected database for Preview B.
  3. A side-effect check: exercise publish, upload and notification paths; confirm they reach only test destinations.
  4. A merge and cleanup check: exclude temporary branch database overrides from the production merge, retain the intended shared Preview baseline, and assign cleanup for separately provisioned test resources. If using Containers, also check for leftover generated apps: deleting a Preview can leave its container app behind. Container cleanup guidance

Keep Preview access restricted too: database isolation is not a search-indexing policy. Use the separate staging access and indexing workflow before sharing review URLs.