
Your Wrangler Staging Environment May Share Production Data
Check whether Wrangler staging is missing bindings or points at production resources, then isolate D1 and make every deploy target explicit.
Start with the resource IDs, not the Worker names. If env.staging and env.production contain the same database_id, both Workers can reach the same D1 database. A separate staging Worker does not make a shared binding safe.
Wrangler environments have two different binding traps
Cloudflare documents bindings and environment variables as non-inheritable. That creates the first trap: a binding at the top level can disappear when you select staging or production. Each named environment needs its own declaration.
The second trap looks safer because the config is complete. Both environments declare DB, but both declarations point at the same resource. The Worker names differ while the stored data does not.
The risky config is valid JSONC
In the Wrangler configuration reference, database_id uniquely identifies a D1 database. Repeating it is the important mistake here. Repeating the binding name DB is normal because the application code should use the same env.DB interface in every environment.
{
"name": "orders-api",
"env": {
"staging": {
"d1_databases": [{
"binding": "DB",
"database_name": "orders-production",
"database_id": "prod-database-uuid"
}]
},
"production": {
"d1_databases": [{
"binding": "DB",
"database_name": "orders-production",
"database_id": "prod-database-uuid"
}]
}
}
}A staging request that inserts, updates, or deletes through env.DB now acts on the production database. The config parses, the Worker deploys, and the bug sits outside the TypeScript type system.
Give staging its own resource identity
Create a staging database, apply only the schema and seed data you are willing to use outside production, then replace the staging ID. Cloudflare's D1 environment guide shows staging and production with different database names and UUIDs.
npx wrangler d1 create orders-staging{
"name": "orders-api",
"env": {
"staging": {
"d1_databases": [{
"binding": "DB",
"database_name": "orders-staging",
"database_id": "staging-database-uuid"
}]
},
"production": {
"d1_databases": [{
"binding": "DB",
"database_name": "orders-production",
"database_id": "prod-database-uuid"
}]
}
}
}Make the deploy target visible in the command
A plain wrangler deploy targets the top-level configuration. It does not mean “use env.production.” Use the environment flag in scripts so a reviewer can see the target. A workers-sdk issue about this naming confusion shows why a successful command can still select the wrong configuration.
{
"scripts": {
"deploy:staging": "wrangler deploy --env staging",
"deploy:production": "wrangler deploy --env production"
}
}Audit every stateful binding, not only D1
The same identity check applies when an environment declares a KV namespace, R2 bucket, Hyperdrive configuration, or Vectorize index. Keep the binding name stable for application code, but give staging a separate target when writes or test data must be isolated.
- List every binding under env.production and env.staging.
- Compare the resource identity, not only the binding and display names.
- Create separate state for non-production writes and migrations.
- Put --env staging or --env production in every deploy script.
Turn the review into a repeatable check
I built FlareCheck to make this review local and deterministic. FC005 finds non-inherited bindings that are missing from a named environment. FC008 compares matching bindings in staging and production and warns when their D1, KV, R2, Hyperdrive, or Vectorize identities are equal. The fixture and rule are open source, so the result is inspectable.
npx flarecheck --strictA staging label is not an isolation boundary. Separate the resource IDs, declare every non-inherited binding, and make the deploy target part of the command.
Reproduce the example
Open the repositoryReference: v0.2.1
npx flarechecknpx flarecheck ./tests/fixtures/shared-resource --strictSources and further reading
- Wrangler environments · Cloudflare
- D1 environments · Cloudflare
- Wrangler configuration reference · Cloudflare
- wrangler deploy and env.production confusion · cloudflare/workers-sdk