Skip to content
SRE & DevOpsDeep Dive Published Updated 6 min readViews unavailable

Cloudflare Workers and Pages: Wrangler Local Development, Staging, and Safe Rollouts

Separate local bindings, preview environments, production resources, Worker versions, traffic deployments, and persistent storage when shipping with Wrangler.

Cloudflare Workers and Pages let teams ship code close to users, but a green local run does not prove that production bindings, data, or routing are correct. The key is to separate four things that are often conflated: local execution, environment configuration, code versions, and deployments that receive traffic. This guide focuses on those boundaries and uses Wrangler commands as examples; check the current Wrangler version and platform documentation before copying commands into a release system.

Make local development useful without giving it production state

wrangler dev runs a Worker locally using the Workers runtime model. Local bindings are emulated by default, which makes ordinary iteration safer and faster, but local behavior is still a simulation of a configured remote service. Validate compatibility settings, binding names, schema assumptions, and service error handling in a controlled non-production environment before release.

Some bindings support a remote development mode. A remote binding means local Worker code can call a real Cloudflare resource; it does not mean that resource is a disposable mock. Writes to a remote D1 database, R2 bucket, KV namespace, Durable Object, or other supported service can affect real data according to the permissions and behavior of that resource. Use dedicated development resources, sample data, scoped credentials, and explicit cleanup. Never enable remote access to a production binding just to make local tests pass.

For a Pages project, wrangler pages dev ./dist serves a built asset directory and can exercise Pages Functions locally when the project includes them. The asset path must match the actual build output. Test both a route that returns a static asset and one that invokes a Function; passing one does not validate the other. Keep local development credentials and production bindings out of developer shells where possible.

Model environments as separate resource configurations

Wrangler environments are not just labels for changing an APP_ENV string. Workers environment configuration has inheritance rules, and non-inheriting bindings and variables need to be declared for the environment that uses them. A staging Worker should have its own name and should point to staging resources, rather than inheriting a production resource ID by omission.

An abbreviated configuration illustrates the intent. The placeholder IDs are not deployable values:

name = "orders-api"
main = "src/index.ts"
compatibility_date = "2026-10-05"
vars = { APP_ENV = "production" }

[[kv_namespaces]]
binding = "CACHE"
id = "PRODUCTION_KV_NAMESPACE_ID"

[env.staging]
name = "orders-api-staging"
vars = { APP_ENV = "staging" }

[[env.staging.kv_namespaces]]
binding = "CACHE"
id = "STAGING_KV_NAMESPACE_ID"

Review the resolved configuration for each environment, not just the base file. Check account, Worker name, compatibility date and flags, routes, secrets, service bindings, and resource IDs. Use wrangler dev --env staging when developing against the declared staging environment, and verify the command’s resolved target before running a command that writes or deploys. A matching binding name does not prove that two environments point at the same data or have the same permissions.

For Pages, configure preview and production bindings separately and test both. A preview deployment that silently uses production D1 or an R2 bucket can turn ordinary review into a production write path. Conversely, a preview can appear healthy while lacking a required binding if the production-only configuration was never exercised. Keep the set of secrets and bindings minimal per environment and make differences visible in review.

Separate a Worker version from a traffic deployment

A Worker version captures code and configuration such as static assets, bindings, and compatibility settings at a point in time. A deployment determines which version or versions serve requests and how traffic is split. By default, wrangler deploy creates and deploys a version immediately, but the versions workflow lets teams upload a version separately and then deploy it deliberately.

An example promotion flow is:

# Upload a version without immediately assigning it production traffic.
npx wrangler versions upload --message "candidate build"

# Review available version identifiers before deployment.
npx wrangler versions list

# Example only: start a 10/90 split using the actual candidate and stable IDs.
npx wrangler versions deploy CANDIDATE_VERSION_ID@10% STABLE_VERSION_ID@90%

Confirm command support and syntax for the installed Wrangler release. A gradual deployment is useful only if you observe the candidate separately. Compare error rates, latency, logs, and application-level outcomes by version; a request percentage is not a health check. Successive requests from one client can reach different versions during a split, so ensure both versions can tolerate overlapping traffic and any shared API or schema state.

Once evidence is acceptable, shift the new version to full traffic using the deployment controls and record the version ID, source commit, configuration, and approval. If the candidate fails, a rollback selects a prior Worker version and changes traffic routing. A rollback may be unavailable if the platform resources used by the selected version have since been deleted or changed, so review the current rollback limitations and preserve compatible bindings. Test the operational command on a non-production Worker, preserve access to the old version, and ensure that the person operating the rollback can identify the intended target unambiguously.

Do not confuse code rollback with data rollback

Worker deployment history does not version or restore the contents of platform storage. Reverting Worker code does not rewind writes in D1, KV, R2, Durable Objects, or an external service. This is especially important when a release performs a data migration or changes how old and new code interpret the same record. Rollback can restore code while leaving data in a newer state that the old code cannot safely handle.

Use expand-and-contract changes: add compatible fields or tables, deploy code that can read old and new forms, migrate data under a separately reviewed procedure, then remove obsolete forms only after every active version no longer needs them. For destructive operations, take a supported backup or use the service’s documented recovery mechanism, define the restore point, and test the recovery path. Worker code rollback and data recovery are separate incident decisions.

Keep Pages preview deployment distinct from Workers gradual rollout

Pages offers preview deployments for builds outside the production branch and a production deployment flow associated with the configured production branch or deployment mechanism. Preview URLs help review a candidate site before publishing it, but they are not the same control as a Workers version traffic split. Do not describe a Pages preview as a percentage-based gradual rollout unless the application has a separate routing design that actually implements that behavior.

For each release, validate the generated asset directory, Functions routes, preview bindings, and production bindings. Confirm which branch or command can update production and protect that path with review and CI checks. If using Wrangler direct uploads, record the target project and branch/environment and inspect the resulting deployment URL before promoting or announcing it.

Release checklist

Before production, review resolved environment configuration and ensure no preview binding points to production state. Run local tests against emulated bindings, then integration tests against isolated staging resources. Verify migration and backward-compatibility steps independently from the code upload. Upload and inspect the exact version or Pages preview, use health signals for any staged traffic shift, and document how to route traffic back without assuming stored data will revert.

Related:

Sources:

Comments