wrangler dev vs deployed: the parity gaps that fake you out
wrangler dev emulates the runtime locally but bindings, .dev.vars, and routing behave differently than production. The checklist that stops it works locally, fails deployed.
wrangler dev vs deployed parity
wrangler dev runs your Worker in a local workerd with emulated bindings. It is close to production, not identical. The gaps:
Bindings
- Local dev uses local emulations or preview resources, not your production KV namespace / D1 database / R2 bucket, unless you configure otherwise. Writing test data in dev and expecting it in production (or vice versa) is the classic confusion.
- A binding missing its
idin config may silently fall back or fail locally while working remotely. Always fill in ids.
Secrets and vars
- Local secrets come from
.dev.vars(or.env, not both;.dev.varswins and.envis ignored when both exist). Production secrets come fromwrangler secret put/ dashboard. A secret present locally but never uploaded is the number one "works locally" failure. - Use
secrets.requiredin config so a missing secret warns in dev instead of 500ing in production.
Routing
wrangler devserves on a local URL, not your routes. Route-pattern bugs (wrong specificity, missing route) only appear after deploy. Verify routes with a real deploy to a staging environment, not just dev.- The Vite plugin path (
vite dev) selects environments viaCLOUDFLARE_ENV; plainwrangler devuses--env. Mixing the two flags across tools selects different configs silently.
Errors
- Runtime errors surface in the dev console; in production they surface as error codes (1101 worker threw, 1102 CPU exceeded) in Workers Logs / Tail. Set up log viewing before you need it, not after the first 1101.
Checklist
- Pre-deploy: secrets uploaded, binding ids present, routes verified on a staging deploy.
- Post-deploy: hit the real URL, check logs, confirm the code path that dev never exercised (cron, queue consumer, WebSocket).
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.