Skip to content

Cloudflare Workers

Varlock provides a robust solution for managing environment variables in Cloudflare Workers, offering validation, type safety, and security features that go beyond Cloudflare’s built-in environment variable and secrets handling.

Both approaches below use varlock-wrangler — a thin wrapper around wrangler that automatically resolves and uploads your env vars as Cloudflare secrets and vars during deployment, and injects them into miniflare during local dev.

  1. Using varlock-wrangler - A thin wrapper for wrangler that injects env vars correctly, along with a one-line init import in your worker
  2. With the Vite plugin - If you’re already using the Cloudflare Workers Vite plugin, you can add the varlock Cloudflare Vite plugin to automatically inject env vars and init code

Replace your wrangler commands with varlock-wrangler and initialize varlock in your worker code with a single import. It’s a thin wrapper that wires up your env vars correctly, and passes everything else through unchanged.

  1. Install packages

    Terminal window
    npm install @varlock/cloudflare-integration varlock
  2. Run varlock init to set up your .env.schema file

    This will guide you through setting up your .env.schema file, based on your existing .env file(s). Make sure to review it carefully.

    Terminal window
    npm exec -- varlock init
  3. Add the varlock init import to your worker entry point

    This initializes varlock’s ENV proxy and applies console redaction and response leak detection (unless disabled):

    src/index.ts
    import '@varlock/cloudflare-integration/init';
    import { ENV } from 'varlock/env';
    export default {
    async fetch(request, env, ctx) {
    // both work:
    console.log(ENV.MY_VAR); // varlock (recommended)
    console.log(env.MY_VAR); // native Cloudflare
    return new Response('Hello!');
    },
    };
  4. Update your package.json scripts to use varlock-wrangler

    Use varlock-wrangler as a drop-in replacement for wrangler:

    package.json
    {
    "scripts": {
    "dev": "varlock-wrangler dev",
    "deploy": "varlock-wrangler deploy",
    "types": "varlock-wrangler types",
    }
    }

    If you deploy via Cloudflare Workers Builds instead of a local/CI script, override the deploy command in your Cloudflare dashboard under Settings → Build → Deploy command — see Workers Builds below.

  • In dev: varlock-wrangler dev resolves your env and injects it into wrangler using --env-file with a named pipe (unix/mac) or temp file (windows). It also watches your .env files and automatically restarts wrangler when they change - something wrangler dev doesn’t do.
  • In production: varlock-wrangler deploy (and varlock-wrangler versions upload) attaches non-sensitive values as Cloudflare vars (via --var) and sensitive values as Cloudflare secrets via --secrets-file. The worker reads them at runtime via import { env } from 'cloudflare:workers'.

If you’re building with Vite, varlockCloudflareVitePlugin wraps the Cloudflare Workers Vite plugin and adds env var + varlock init injection — no extra init import needed, and both ENV.MY_VAR and native env.MY_VAR work in dev and production.

For SvelteKit on Cloudflare, use the dedicated varlockSvelteKitCloudflarePlugin from @varlock/cloudflare-integration/sveltekit instead.

  1. Install packages

    Terminal window
    npm install @varlock/cloudflare-integration @cloudflare/vite-plugin varlock

    @cloudflare/vite-plugin is an (optional) peer dependency — this plugin wraps it, so you need it installed in the same project. SvelteKit users should omit it (see the SvelteKit callout at the top of this page).

  2. Run varlock init to set up your .env.schema file

    Terminal window
    npm exec -- varlock init
  3. Update your Vite config

    Replace the cloudflare() plugin with varlockCloudflareVitePlugin() — it is a thin wrapper of the Cloudflare vite plugin and passes through all config:

    vite.config.ts
    import { defineConfig } from 'vite';
    import { cloudflare } from '@cloudflare/vite-plugin';
    import { varlockCloudflareVitePlugin } from '@varlock/cloudflare-integration';
    export default defineConfig({
    plugins: [
    cloudflare(),
    varlockCloudflareVitePlugin(),
    // other plugins ...
    ],
    });

    Any options you were passing to cloudflare() can be passed directly to varlockCloudflareVitePlugin() at the top level.

  4. Deploy with varlock-wrangler

    Use varlock-wrangler deploy instead of wrangler deploy in your deploy script:

    package.json
    {
    "scripts": {
    "dev": "vite dev",
    "build": "vite build",
    "deploy": "npm run build && varlock-wrangler deploy"
    }
    }

    If you deploy via Cloudflare Workers Builds instead of a local/CI script, override the deploy command in your Cloudflare dashboard under Settings → Build → Deploy command — see Workers Builds below.

  • In dev: Resolved vars are automatically injected into miniflare’s bindings.
  • In production: Non-sensitive values are statically replaced at build time by vite. varlock-wrangler deploy sets non-sensitive values as Cloudflare vars and sensitive values as secrets.

If you were previously using varlockVitePlugin() from @varlock/vite-integration with Cloudflare Workers:

  1. Install @varlock/cloudflare-integration (you can remove @varlock/vite-integration — it’s included)
  2. In vite.config.ts, replace both varlockVitePlugin() and cloudflare() with varlockCloudflareVitePlugin()
  3. Replace wrangler deploy with varlock-wrangler deploy in your deploy script
vite.config.ts
import { varlockVitePlugin } from '@varlock/vite-integration';
import { cloudflare } from '@cloudflare/vite-plugin';
import { varlockCloudflareVitePlugin } from '@varlock/cloudflare-integration';
export default defineConfig({
plugins: [
varlockVitePlugin(),
cloudflare(),
varlockCloudflareVitePlugin(),
],
});

Your secrets will no longer be bundled into the JS artifact — they’ll be stored in Cloudflare’s secret management instead.


varlock-wrangler is a thin wrapper around wrangler. It enhances the commands below; everything else (tail, secret list, etc.) is passed through unchanged, so you can use varlock-wrangler everywhere or just for these commands.

Wraps wrangler dev with automatic env injection. Resolves your environment variables, injects them into miniflare, and watches your .env files to restart wrangler when they change.

Resolves your environment variables from .env.schema + .env files, then uploads non-sensitive values as Cloudflare vars (--var), sensitive values as Cloudflare secrets (--secrets-file), and includes a __VARLOCK_ENV secret containing the full resolved env graph for the varlock runtime.

Generates Cloudflare Worker types (the Env interface) including all varlock-managed environment variables, so your env.MY_VAR access is properly typed alongside other Cloudflare bindings (KV, D1, etc.).


Both integration approaches automatically enable log redaction (sensitive values are masked in console output) and response leak detection (responses are scanned for accidentally exposed secrets). These are enabled by default and can be disabled in your .env.schema using root decorators:

.env.schema
# @redactLogs=false
# @preventLeaks=false

For more details, see the root decorators reference.


Varlock can load multiple environment-specific .env files (e.g., .env.development, .env.preview, .env.production) by using the @currentEnv root decorator.

The simplest approach is to use the built-in VARLOCK_ENV variable, which auto-detects the deployment environment on most CI platforms — including Cloudflare Workers Builds (via WORKERS_CI_BRANCH), Vercel, Netlify, and others. Locally it resolves to development, and during tests to test.

.env.schema
# @currentEnv=$VARLOCK_ENV
# ---

If you need more control — for example mapping specific branches to specific environments — you can define your own env-selection var instead:

.env.schema
# @currentEnv=$APP_ENV
# ---
WORKERS_CI_BRANCH=
# @type=enum(development, preview, production, test)
APP_ENV=remap($WORKERS_CI_BRANCH, "main", production, /.*/, preview, undefined, development)

For more information, see the environments guide.


If you deploy via Cloudflare Workers Builds, two pieces of setup are required in the dashboard — neither can be configured from a file in the repo:

  1. Override the Deploy command

    Under Settings → Build → Deploy command, replace the default npx wrangler deploy with:

    Terminal window
    npx varlock-wrangler deploy

    Without this override, Cloudflare runs stock wrangler deploy, which skips varlock’s env resolution and leaves your worker without its resolved vars/secrets at runtime.

  2. Set any secret-zero vars under Build variables

    Any env vars that varlock itself needs during load — for example a 1Password service account token, a GCP key — must be set under Settings → Build → Variables and Secrets. These are made available to the build step, where varlock-wrangler deploy resolves your full env graph and uploads the result to the worker runtime as regular vars/secrets.

    Vars that only your worker needs at runtime (not varlock itself) don’t need to be set here — they’ll be resolved by varlock and set automatically by varlock-wrangler deploy.

Varlock vs Cloudflare’s built-in env management

Section titled “Varlock vs Cloudflare’s built-in env management”

Cloudflare Workers have built-in support for vars and secrets, but managing them across environments quickly becomes painful. Here’s what Varlock adds:

  • Single source of truth — Instead of scattering config across the Cloudflare dashboard, wrangler.toml, .dev.vars, and your code, everything is defined in one .env.schema file that works across local dev, preview, and production.
  • Validation before deploy — Cloudflare only has basic required var validation. Varlock catches missing vars, wrong types, and invalid values before your worker starts — not when it crashes at runtime.
  • Pull secrets from vaults — Instead of manually running wrangler secret put or copy-pasting values in the dashboard, pull secrets directly from 1Password, AWS Secrets Manager, HashiCorp Vault, and more.
  • Log redaction & leak prevention — Cloudflare doesn’t prevent you from accidentally console.log-ing a secret or including one in a response body. Varlock automatically redacts sensitive values in logs and scans outgoing responses for leaked secrets.
  • Simpler multi-environment setup — Wrangler’s [env.staging] / [env.production] blocks duplicate config and don’t support .env file overrides. Varlock uses familiar .env.production / .env.preview files with a single schema, and auto-detects the current environment in CI.
  • Local dev that matches production.dev.vars is completely disconnected from your production secrets. With Varlock, local dev resolves from the same schema and same secret sources, so there’s no drift between environments.
  • AI-safe by design — Your .env.schema gives AI coding tools full context on your config (names, types, descriptions) without ever exposing secret values.