Skip to content

Workers Environment Variables and Secrets

DodaTech 4 min read

In this tutorial, you'll learn about Workers Environment Variables and Secrets. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Cloudflare Workers environment variables let you inject configuration values and encrypted secrets into your Worker code at runtime, keeping API keys, database URLs, and environment-specific settings separate from your source code.

Why Workers Environment Variables Matter

Hardcoding configuration values in your Worker source code creates security risks and makes deployments fragile. Environment variables separate configuration from code, letting you promote the same Worker across development, staging, and production environments without editing a single line. Secrets are encrypted at rest and never exposed in logs or error messages. Combined with Cloudflare Wrangler CLI, you can manage environment-specific variables as part of your normal deployment workflow.

Real-world use: A multi-tenant API Gateway Worker uses environment variables to route requests to different backend URLs per tenant. The staging Worker reads API_BASE_URL=https://staging-api.example.com while production uses API_BASE_URL=https://api.example.com -- the same source code, different configurations.

Environment Variable Architecture

flowchart LR
    W[wrangler.toml] --> B[Build/Bundle]
    B --> E[Workers Runtime]
    E --> V[env.API_KEY]
    E --> S[env.DATABASE_URL]
    S -->|Encrypted| K[Secrets storage]
    V --> P[Plaintext vars]
    E --> W2[waitUntil background tasks]
    style E fill:#f90,color:#fff
    style K fill:#f90,color:#fff

Defining Plaintext Variables in wrangler.toml

Add non-sensitive configuration directly in your wrangler.toml file.

name = "my-worker"
main = "src/index.js"

[vars]
API_BASE_URL = "https://api.example.com"
LOG_LEVEL = "debug"
MAX_RETRIES = "3"
export default {
  async fetch(request, env) {
    console.log(`Log level: ${env.LOG_LEVEL}`);
    console.log(`Max retries: ${env.MAX_RETRIES}`);
    const response = await fetch(`${env.API_BASE_URL}/health`);
    return new Response(JSON.stringify({ status: response.ok ? 'ok' : 'fail' }), {
      headers: { 'Content-Type': 'application/json' }
    });
  }
}

Expected output: The Worker logs the log level and max retries, then fetches the health endpoint from the configured API_BASE_URL. Changing the URL in wrangler.toml and redeploying updates the behavior without touching code.

Managing Secrets with Wrangler

Secrets are encrypted values set via the Wrangler CLI. They are never stored in your Repository.

wrangler secret put DATABASE_URL
# Enter the secret value: postgresql://user:pass@prod-db.example.com:5432/app
wrangler secret put API_KEY
# Enter the secret value: sk-proj-xxxx
export default {
  async fetch(request, env) {
    const dbUrl = env.DATABASE_URL;
    const apiKey = env.API_KEY;
    return new Response(`Database configured: ${dbUrl ? 'yes' : 'no'} | API key set: ${apiKey ? 'yes' : 'no'}`, {
      headers: { 'Content-Type': 'text/plain' }
    });
  }
}

Expected output: The response confirms both secrets are available at runtime. Secrets are injected as environment variables but are encrypted in transit and at rest. Running wrangler secret list shows secret names but never their values.

Environment-Specific Configurations

Use the --env flag to maintain separate configurations for different environments.

# wrangler.toml
name = "my-worker"
main = "src/index.js"

[vars]
LOG_LEVEL = "info"

[env.staging]
vars = { LOG_LEVEL = "debug", API_BASE_URL = "https://staging-api.example.com" }

[env.production]
vars = { LOG_LEVEL = "warn", API_BASE_URL = "https://api.example.com" }
wrangler deploy --env staging
wrangler deploy --env production
export default {
  async fetch(request, env) {
    const logLevel = env.LOG_LEVEL || 'info';
    const apiBase = env.API_BASE_URL || 'https://default.api.example.com';
    return new Response(JSON.stringify({ environment: env.ENVIRONMENT || 'default', logLevel, apiBase }), {
      headers: { 'Content-Type': 'application/json' }
    });
  }
}

Expected output: Deploying with --env staging sets LOG_LEVEL to debug and API_BASE_URL to the staging URL. The --env production variant uses warn and the production URL. The same source code behaves differently per environment.

Common Errors

Error Cause Fix
Variable is not defined Accessing a variable before it is set Add the variable to [vars] or use wrangler secret put
SyntaxError: Unexpected identifier Using Process.env instead of env parameter Use env.MY_VAR in the module syntax fetch handler
Missing binding Referencing a secret that does not exist Run wrangler secret list to verify the secret exists
Cannot read properties of undefined Accessing env outside the fetch handler Pass env from the fetch handler to helper functions
Value must be a string Setting a non-string value in wrangler.toml vars Wrap numbers and booleans in quotes

Practice Questions

  1. What is the difference between [vars] in wrangler.toml and wrangler secret put?
  2. How do you access environment variables inside a Worker using module syntax?
  3. Why should you never store secrets like API keys directly in wrangler.toml?

FAQ

Can I change a secret without redeploying the Worker?

Yes, secrets are read at runtime. Running wrangler secret put KEY_NAME updates the value immediately for all subsequent requests. No redeployment is needed.

Are environment variables accessible in local development with wrangler dev?

Yes, Wrangler reads both [vars] from wrangler.toml and locally stored secrets from .dev.vars when running wrangler dev. This lets you test environment-specific behavior without deploying.

Summary

Environment variables and secrets keep your Worker configuration flexible and secure. Plaintext variables in wrangler.toml handle non-sensitive settings, while wrangler secret put manages encrypted credentials. Multi-environment support with --env lets you promote the same code across development, staging, and production. This approach is used by Doda Browser's privacy services to manage environment-specific API endpoints and encryption keys without exposing secrets in version control. Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro -- security-first tools for the modern web.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro