Routing and configuration

Separate variables and secrets

Put ordinary environment configuration in versioned vars and sensitive values in the Cloudflare secret store.

Not every setting is a secret. The environment name, a feature flag, a public base URL: those are variables. They go in wrangler.jsonc and get committed to Git. An API token, a signing key, a database password: those are secrets. They must never enter Git.

Both show up on env. The difference is where the value lives.

Variables

Variables sit in the vars block of the config:

{
  "vars": { "ENVIRONMENT": "production" }
}

Read it as c.env.ENVIRONMENT after running wrangler types.

Secrets

Secrets go into Cloudflare’s secret store through Wrangler. It prompts for the value so nothing lands in your shell history:

npx wrangler secret put API_TOKEN
npx wrangler secret list

The list command prints names only, never values. That’s the point.

For local development, put secrets in a .dev.vars file at the project root, one KEY=value per line, and add it to .gitignore. wrangler dev loads it automatically.

Classify by impact

The rule I use: ask what happens if this value shows up in a public log. If the answer is “nothing”, it’s a variable. If the answer involves someone getting access they shouldn’t have, it’s a secret. Convenience doesn’t enter the decision.

Configure each environment on its own

Wrangler environments (env.staging, env.production in the config) do not inherit vars from the top level. A variable you set at the root does not exist in staging unless you set it there too. Secrets are per Worker and per environment as well. Set them explicitly for each one, and check with wrangler secret list --env staging.

Rotation and rollback

Use a separate credential per environment, each with the smallest permissions that work. Rotating one goes like this: add the new secret, deploy code that reads it, verify the path that depends on it, then revoke the old one.

Here is the catch. A rollback reactivates older code. If that older version needs the secret you just revoked, the rollback itself breaks production. Before revoking, check that the version you would roll back to doesn’t depend on the old credential.

Git is not the only leak

A clean repo doesn’t mean a clean secret. Logs, thrown exceptions, response bodies, and that .dev.vars file you forgot to ignore are all leak paths. Never log env as a whole, and never echo a secret back in a debug endpoint.

Try it on your project. Add the ENVIRONMENT variable, create a practice secret with wrangler secret put, and put the same key in .dev.vars. Then add a temporary route that returns { environment: c.env.ENVIRONMENT, hasToken: Boolean(c.env.API_TOKEN) }. You confirm both values are readable without ever printing the token.

Lesson completed