diff --git a/src/content/docs/workers/configuration/environments.mdx b/src/content/docs/workers/configuration/environments.mdx new file mode 100644 index 00000000000000..08b06d1b073785 --- /dev/null +++ b/src/content/docs/workers/configuration/environments.mdx @@ -0,0 +1,1046 @@ +--- +pcx_content_type: configuration +title: Environments +sidebar: + order: 10 +head: [] +description: You can add environment variables, which are a type of binding, to attach text strings or JSON values to your Worker. +--- + +import { + Details, + LinkCard, + Render, + PackageManagers, + WranglerConfig, + InlineBadge, + CardGrid, + Card, + Type, + TypeScriptExample, + Tabs, + TabItem, +} from "~/components"; + +Every Worker application has three default environments: **development**, **preview**, and **production**. Each environment defines the **[resource bindings](/workers/runtime-apis/bindings/)** (like [KV namespaces](/kv/), [R2 buckets](/r2/)) and **configuration** (like [environment variables](/workers/configuration/environment-variables/) and [secrets](/workers/configuration/secrets/)) that your Worker uses in that context. + +- **[Development](#development-environment)** - For developing on your local machine, using the [Wrangler CLI](/workers/wrangler/) or [Cloudflare Vite plugin](/workers/vite-plugin/). + +- **[Preview](#preview-environment)** - For testing changes in isolated [preview deployments](#preview-deployments) before merging to production. Each pull request gets its own unique preview deployment with a dedicated URL, using your [preview environment](#preview-environment) settings. + +- **[Production](#production-environment)** - For serving real user traffic. Your [production deployment](#production-deployments) runs on your **[production domain](/workers/configuration/routing/)** and uses production [bindings](/workers/runtime-apis/bindings/), [environment variables](/workers/configuration/environment-variables/), and [secrets](/workers/configuration/secrets/). + +**Start from CLI** - scaffold a full-stack app with a React SPA, Cloudflare Workers API, and the [Cloudflare Vite plugin](/workers/vite-plugin/) and configure environments: + + +--- + +**Or just deploy** - create a full-stack app using React, Hono API and Vite, with CI/CD and preview deployments set up for you. + +[![Deploy to Workers](https://deploy.workers.cloudflare.com/button)](https://dash.cloudflare.com/?to=/:account/workers-and-pages/create/deploy-to-workers&repository=https://github.com/cloudflare/templates/tree/main/vite-react-template) + +## Environment configuration + +You define all three environments in your [Wrangler configuration file](/workers/wrangler/configuration/). + + +```jsonc title="wrangler.jsonc" +{ + "name": "my-worker", + "compatibility_date": "$today", + "development": { + "kv_namespaces": [ + { + "binding": "MY_KV" + } + ] + }, + "preview": { + "vars": { + "ENVIRONMENT": "preview" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "abc123preview" + } + ] + }, + "production": { + "vars": { + "ENVIRONMENT": "production" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "xyz789production" + } + ] + } +} +``` + + +## Required environment configuration + +- **Bindings:** For each environment, you need to declare the **[bindings](/workers/runtime-apis/bindings/)** your Worker code will interact with (for example, calling `env.MY_KV`). This makes sure your Worker code has everything it needs to work at runtime. + +- **Environment variables:** For your **[preview](#preview-environment)** and **[production](#production-environment)** environments, you also need to define the **[environment variables](/workers/configuration/environment-variables/)** (`vars`) your Worker needs at runtime. This isn't required for your **[development](#development-environment)** environment, as you can provide environment variables and secrets via a `.env` file (or pull down your **development** settings from the dashboard with `wrangler env pull`). + +- **Resource IDs or names:** For your **[preview](#preview-environment)** and **[production](#production-environment)** environments, you need to specify which deployed resources on your Cloudflare account should be used. For your **[development](#development-environment)** environment, you only need to define the binding types without any real IDs or names. [Miniflare](https://miniflare.dev/) will create local simulations for all resources, or you can specify an ID/name of a deployed resource to connect to it remotely during local development. + +- **Secrets:** [Secrets](/workers/configuration/secrets/) should never be defined in Wrangler configuration. You can provide secrets for your **[development](#development-environment)** environment with a `.env` file (or pulling them down from the dashboard with `wrangler env pull`). To add secrets to your **[production](#production-environment)** and **[preview](#preview-environment)** environments, you can add them in the dashboard or with `wrangler secret put` (for **production** secrets) and `wrangler secret put --preview` (for **preview** secrets). + +## Development environment + +Your **development** environment is a collection of settings that your Worker application uses when you run [`wrangler dev`](/workers/wrangler/commands/#dev) or `vite dev.` These settings include: + +- What [bindings](/workers/runtime-apis/bindings/) your Worker code needs to interact with (such as making calls to `env.MY_KV`). +- What [environment variables](/workers/configuration/environment-variables/) and [secrets](/workers/configuration/secrets/) your Worker code needs during local development. + +#### Development bindings + +You need to define all **[bindings](/workers/runtime-apis/bindings/)** in your [Wrangler configuration file](/workers/wrangler/configuration/) under the `development` block. + + +```jsonc title="wrangler.jsonc" +{ + "development": { + "kv_namespaces": [ + { + "binding": "MY_KV" + } + ] + } +} +``` + + +**Local bindings:** When you start your development environment, [Miniflare](https://miniflare.dev/) looks at this configuration block and creates **local** simulations of all resources so that you can develop offline and without incurring costs. + +**Remote bindings:** You can also connect to a deployed resource during local development, making it easier to get started quickly without seeding a local database. You just provide a deployed resource's ID or name for that [binding](/workers/runtime-apis/bindings/): + + +```jsonc title="wrangler.jsonc" +{ + "development": { + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "abc123preview" + } + ] + } +} +``` + + +#### Development environment variables & secrets + +You can provide your development environment's environment variables and secrets by placing them in a `.env` or `.env.local` file in your project root: + +```ini title=".env" +API_KEY=your-dev-api-key +DATABASE_URL=http://localhost:5432 +``` + +#### `wrangler env pull` + +To make it easier to get started and share a local development setup as a team, you can run: + + + +This command pulls down your **development** environment variables and secrets from the dashboard, and places them in a `.env.local` file. If you want your `.env.local` file to be populated with values from your **preview** or **production** environment, just specify the environment name: + +**Pull down preview environment variables and secrets** + + + +**Pull down production environment variables and secrets** + + + +## Preview environment + +Your **preview** environment defines the default settings that all [preview deployments](#preview-deployments) share, including: + +- The [bindings](/workers/runtime-apis/bindings/) and resources your preview deployments connect to (like [KV namespaces](/kv/), [R2 buckets](/r2/), [D1 databases](/d1/)). +- The [environment variables](/workers/configuration/environment-variables/) and [secrets](/workers/configuration/secrets/) preview deployments use. + +You have one **preview environment** (the shared settings), but many **preview deployments** (one running deployment per +branch). Each preview deployment uses the preview environment's settings by default, but you can [override values for a specific branch](#override-preview-environment-defaults-for-specific-branches). + +### Preview deployments + +A **preview deployment** is a live, running copy of your Worker application with its own unique URL. Think of it like a sandbox or staging server, but automatically created for each pull request. You can have multiple preview deployments running at the same time - one for each feature branch you're working on. + +Cloudflare automatically creates a new preview deployment each time: + +- You push a commit to a branch that's not your production branch (which defaults to `main`). You need to [connect your Git repository](/workers/ci-cd/git-integration/) to Cloudflare for automated preview deployments. If that branch has an open pull request, Cloudflare will post a comment on your PR with your preview deployment's unique URL. +- You run [`wrangler deploy --preview`](/workers/wrangler/commands/#deploy) with the [Wrangler CLI](/workers/wrangler/). + +With preview deployments, you get all the same features that production deployments get, like [Observability](/workers/observability/). Each preview deployment has its own [version history](/workers/configuration/versions-and-deployments/), so you can track changes on a branch over time. + +#### Preview environment bindings & variables + +You need to define all preview **[bindings](/workers/runtime-apis/bindings/)**, the real **resource IDs or names** those bindings connect to, and **[environment variables](/workers/configuration/environment-variables/)** (`vars`) in your [Wrangler configuration file](/workers/wrangler/configuration/) under the `preview` block. + + +```jsonc title="wrangler.jsonc" +{ + "preview": { + "vars": { + "ENVIRONMENT": "preview" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "abc123preview" + } + ] + } +} +``` + + +
+Why do I need to define `vars` in my Wrangler configuration file? + +You need to define vars in your [Wrangler configuration file](/workers/wrangler/configuration/) because Workers uses a different runtime (called [workerd](https://github.com/cloudflare/workerd)) than traditional platforms. + +In traditional platforms like Node.js on a server, the runtime can read environment variables directly from the operating system through something like `process.env` - they're just "there" in the process environment. But the [Workers runtime](/workers/runtime-apis/) doesn't have access to OS-level environment variables. Instead, it only knows about what you explicitly tell it about through [bindings](/workers/runtime-apis/bindings/) in your Wrangler configuration file. + +When you deploy, [Wrangler](/workers/wrangler/) takes everything you've defined in your config file (vars, [KV namespaces](/kv/), [R2 buckets](/r2/), etc.) and packages them up as bindings that get injected into your Worker's execution context. So `vars` aren't "already there" - they have to be explicitly declared and passed into the runtime. + +
+ +#### Preview environment secrets + +You can set the secrets for your preview environment using the Wrangler CLI or dashboard: + +**CLI** + + + +**Dashboard** + +Go to **Settings** > **Environments** > **Secrets** + +By default, all preview deployments share the same secrets. + +### Override preview environment defaults for specific branches + +If a specific branch needs different environment variables or secrets than what's supplied by the shared preview environment, you can override the defaults for that branch. + +#### How branch overrides work + +When you override settings for a branch: + +1. The first time you push to a branch, it automatically deploys using default preview settings. +2. You then set branch-specific overrides using the the dashboard. +3. Cloudflare redeploys your unique preview deployment with the new settings. +4. All future commits to that branch automatically use your overrides. +5. When the branch is deleted, the overrides are cleaned up. + +#### How to override environment variables or secrets + +1. Go to Workers & Pages > select your Worker application +2. Go to **Deployments** > find your **preview deployment** +3. Click Settings > Variables & secrets > Toggle the "Override" button. +4. Add or modify the values you want to override. +5. Click Save - this triggers a new deployment with your overrides. + +## Production environment + +Your **production** environment is for deploying your Worker to a **production domain** so it can serve real users. A **production domain** is the URL that real users access to reach your Worker application - like example.com or my-worker.my-account.workers.dev. + +Your production environment defines the settings your Worker uses when serving production traffic, including: + +- The [bindings](/workers/runtime-apis/bindings/) and resources it connects to (like [KV namespaces](/kv/), [R2 buckets](/r2/), [D1 databases](/d1/)). +- The [environment variables](/workers/configuration/environment-variables/) and [secrets](/workers/configuration/secrets/) it uses. + +### Production deployments + +A **production deployment** is your live, running Worker application serving real user traffic. Your production deployment is available on your [`*.workers.dev` subdomain](/workers/configuration/routing/workers-dev/), [custom domain](/workers/configuration/routing/custom-domains/), or [route](/workers/configuration/routing/routes/). + +Cloudflare automatically deploys to production each time: + +- You push a commit to your production branch (which defaults to `main`). You need to [connect your Git repository](/workers/ci-cd/git-integration/) to Cloudflare for automated production deployments. +- You run [`wrangler deploy`](/workers/wrangler/commands/#deploy) with the [Wrangler CLI](/workers/wrangler/). + +#### Production environment bindings & variables + +You need to define all production **[bindings](/workers/runtime-apis/bindings/)**, the real **resource IDs or names** those bindings connect to, and **[environment variables](/workers/configuration/environment-variables/)** (`vars`) in your [Wrangler configuration file](/workers/wrangler/configuration/) under the `production` block. + + +```jsonc title="wrangler.jsonc" +{ + "production": { + "vars": { + "ENVIRONMENT": "production" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "xyz789production" + } + ] + } +} +``` + + +#### Production environment secrets + +You can set the secrets for your production environment using the Wrangler CLI or dashboard: + +**CLI** + + + +**Dashboard** + +Go to **Settings** > **Environments** > **Production** > **Secrets** + +## Guides + +This guide will walk you through setting up default environments for your Worker application from scratch. For a quickstart that creates an application with environments already configured, use [this template](needs a template) + + + + +You can create a new Worker application using the `create-cloudflare` package: + + + +Move into your directory and build your application: + +```sh +cd my-app && npm run build +``` + +#### Review configuration + +Next, let's look at our [Wrangler configuration file](/workers/wrangler/configuration/). It should look like this: + + + +```jsonc title="wrangler.jsonc" +{ + "name": "my-worker", + "compatibility_date": "$today", + "assets": { + "not_found_handling": "single-page-application", + }, + "development": {}, + "preview": {}, + "production": {}, +} +``` + + + +As you'll see, there are configuration blocks for each **default environment**: [`development`](#development-environment), [`preview`](#preview-environment), and [`production`](#production-environment). Each block will hold the [bindings](/workers/runtime-apis/bindings/) and configuration specific to that environment. + +#### Add bindings and environment variables + +From here, you can add **[bindings](/workers/runtime-apis/bindings/)** and **[environment variables](/workers/configuration/environment-variables/)** to each environment block. + + +```jsonc title="wrangler.jsonc" +{ + "name": "my-worker", + "compatibility_date": "$today", + "assets": { + "not_found_handling": "single-page-application" + }, + "development": { + "kv_namespaces": [ + { + "binding": "MY_KV" + } + ] + }, + "preview": { + "vars": { + "ENVIRONMENT": "preview" + }, + "kv_namespaces": [ + { + "binding": "MY_KV" + } + ] + }, + "production": { + "vars": { + "ENVIRONMENT": "production" + }, + "kv_namespaces": [ + { + "binding": "MY_KV" + } + ] + } +} +``` + + + +In this example, we've added: + +- **[Bindings](/workers/runtime-apis/bindings/):** Within the [`development`](#development-environment), [`preview`](#preview-environment), and [`production`](#production-environment) blocks, we've added a [KV namespace](/kv/) binding `MY_KV`. This allows us to call `env.MY_KV` within our Worker code, but the resources that `env.MY_KV` interacts with will change depending on the environment context. In the next step, Cloudflare will automatically provision **separate KV namespaces** for our preview and production environments upon deployment. + +- **[Environment variables](/workers/configuration/environment-variables/):** We've added `vars` blocks to our [`preview`](#preview-environment) and [`production`](#production-environment) environments, allowing us to use different environment variable values for each environment. For the **[development](#development-environment)** environment, you can place all environment variables (and [secrets](/workers/configuration/secrets/)) in a `.env` file. + +#### Deploy + +Now, let's deploy our Worker application: + + + +Because there aren't any existing [KV namespaces](/kv/) for `MY_KV` to connect to, [Wrangler](/workers/wrangler/) automatically provisions separate **[preview](#preview-environment)** and **[production](#production-environment)** KV namespaces. + +If you look again at your `wrangler.jsonc` file, you'll see that separate KV namespaces have been added to the **[preview](#preview-environment)** and **[production](#production-environment)** environments: + + +```jsonc title="wrangler.jsonc" +{ + "name": "my-worker", + "compatibility_date": "$today", + "assets": { + "not_found_handling": "single-page-application" + }, + "development": { + "kv_namespaces": [ + { + "binding": "MY_KV" + } + ] + }, + "preview": { + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "" + } + ] + }, + "production": { + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "" + } + ] + } +} +``` + + + +And you're done! In the [Cloudflare dashboard](https://dash.cloudflare.com), you should now see in the **Overview** tab your **[production](#production-environment)** deployment, made immediately available on your [`workers.dev` domain](/workers/configuration/routing/workers-dev/). + +You can automate production and preview deployments by [connecting your Git repository](/workers/ci-cd/git-integration/) to Cloudflare, making it easy to setup [preview deployments](#preview-deployments) with separate resources and configuration for your pull requests. + + + + + +1. Go to **Workers & Pages** in the [Cloudflare dashboard](https://dash.cloudflare.com). +2. Select **Create application**. +3. Choose from: + - Gallery of production-ready templates + - Import an existing Git repository + - Clone a public repository +4. Connect your Git provider and configure your project. +5. Select **Deploy**. + +Your Worker will be immediately deployed with all three default environments setup. You can see what [bindings](/workers/runtime-apis/bindings/) each environment uses in the **Bindings** tab, as well as the [environment variables](/workers/configuration/environment-variables/) and other settings for each environment in **Settings** > **Environments**. + +#### Pull down your development environment + +First, clone your repository locally: + +```bash +git clone +cd +``` + +Then, run `wrangler env pull` to pull down your **[development](#development-environment)** environment settings. + + + +By default, `wrangler env pull` pulls down any settings stored in the dashboard (including [environment variables](/workers/configuration/environment-variables/) and [secrets](/workers/configuration/secrets/)) for your **[development](#development-environment)** environment, and populates an `env.local` file with those values. You can pull down another environment's configuration by running `wrangler env pull --preview` or `wrangler env pull --production.` When you run [`wrangler dev`](/workers/wrangler/commands/#dev) (or `vite dev` if using the [Cloudflare Vite plugin](/workers/vite-plugin/)), the development server will look for this file to use for your **[development](#development-environment)** environment's configuration. + +#### Test changes with a preview deployment + +Now let's make a change and create a [preview deployment](#preview-deployments) to test it: + +1. Create a new branch for your changes: + +```bash +git checkout -b feature/my-new-feature +``` + +2. Make changes to your Worker code and test locally with [`wrangler dev`](/workers/wrangler/commands/#dev). + +3. Commit and push your changes to the new branch: + +```bash +git add . +git commit -m "Add new feature" +git push origin feature/my-new-feature +``` + +4. Create a pull request in your Git repository (GitHub, GitLab, etc.). + +5. Cloudflare automatically creates a **[preview deployment](#preview-deployments)** using your **[preview environment](#preview-environment)** settings. Within moments, you'll see a comment on your pull request with a unique URL to your preview deployment. + +Your preview deployment uses the [bindings](/workers/runtime-apis/bindings/), [environment variables](/workers/configuration/environment-variables/), and [secrets](/workers/configuration/secrets/) defined in your [preview environment](#preview-environment), allowing you to test your changes with isolated resources before merging to production. + + + + +This guide shows how to deploy to both your [production](#production-environment) and [preview](#preview-environment) environments using the Cloudflare API. + +#### Deploy to production + +Deploy to production by creating a new version and deployment for your production Worker: + +```bash +# Set your credentials +ACCOUNT_ID="your_account_id" +API_TOKEN="your_api_token" +PROD_WORKER_NAME="my-app-production" +PROD_WORKER_ID="your_production_worker_id" + +# Prepare your script +PROD_SCRIPT_BASE64=$(cat ./dist/production.mjs | base64) + +# Create a new version +VERSION_RESPONSE=$(curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/workers/$PROD_WORKER_ID/versions" \ + -X POST \ + -H "Authorization: Bearer $API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "compatibility_date": "$today", + "main_module": "production.mjs", + "modules": [ + { + "name": "production.mjs", + "content_type": "application/javascript+module", + "content_base64": "'$PROD_SCRIPT_BASE64'" + } + ] + }') + +VERSION_ID=$(echo "$VERSION_RESPONSE" | jq -r '.result.id') + +# Deploy the new version (send 100% of traffic to it) +curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/scripts/$PROD_WORKER_NAME/deployments" \ + -X POST \ + -H "Authorization: Bearer $API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "strategy": "percentage", + "versions": [ + { + "percentage": 100, + "version_id": "'$VERSION_ID'" + } + ] + }' +``` + +#### Deploy a preview for a feature branch + +Create a [preview deployment](#preview-deployments) by posting your script to the Application's `/previews` endpoint. The API automatically creates a new temporary Worker, copies the settings from your [preview environment](#preview-environment), and deploys your script: + +```bash +# Set your credentials +ACCOUNT_ID="your_account_id" +API_TOKEN="your_api_token" +APP_ID="your_application_id" +BRANCH_NAME="feature-xyz-123" + +# Prepare your script +FEATURE_SCRIPT_BASE64=$(cat ./dist/feature.mjs | base64) + +# Deploy the feature branch +PREVIEW_RESPONSE=$(curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/applications/$APP_ID/previews" \ + -X POST \ + -H "Authorization: Bearer $API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "annotations": { + "workers/branch": "'$BRANCH_NAME'" + }, + "compatibility_date": "$today", + "main_module": "feature.mjs", + "modules": [ + { + "name": "feature.mjs", + "content_type": "application/javascript+module", + "content_base64": "'$FEATURE_SCRIPT_BASE64'" + } + ] + }') + +# Get the new Worker's ID for cleanup later +EPHEMERAL_WORKER_ID=$(echo "$PREVIEW_RESPONSE" | jq -r '.result.worker_id') + +echo "Feature branch deployed to temporary worker: $EPHEMERAL_WORKER_ID" +``` + +#### Clean up preview deployments + +When your pull request is merged or closed, delete the temporary Worker: + +```bash +curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/workers/$EPHEMERAL_WORKER_ID" \ + -X DELETE \ + -H "Authorization: Bearer $API_TOKEN" +``` + + + + +This guide shows how to deploy to both your [production](#production-environment) and [preview](#preview-environment) environments using the [Cloudflare TypeScript SDK](https://github.com/cloudflare/cloudflare-typescript). + +Install the SDK: + +```bash +npm install cloudflare +``` + +#### Deploy to production + +Deploy to production by creating a new version and deployment for your production Worker: + +```typescript +import Cloudflare from "cloudflare"; +import fs from "fs"; + +const ACCOUNT_ID = process.env.CLOUDFLARE_ACCOUNT_ID; +const API_TOKEN = process.env.CLOUDFLARE_API_TOKEN; +const PROD_WORKER_NAME = "my-app-production"; +const PROD_WORKER_ID = "your_prod_worker_id"; + +const client = new Cloudflare({ apiToken: API_TOKEN }); + +async function deployToProduction() { + const scriptContent = fs.readFileSync("./dist/production.mjs", "utf8"); + const scriptBase64 = Buffer.from(scriptContent).toString("base64"); + + // Create a new version + const version = await client.workers.beta.workers.versions.create( + PROD_WORKER_ID, + { + account_id: ACCOUNT_ID, + main_module: "production.mjs", + compatibility_date: "$today", + modules: [ + { + name: "production.mjs", + content_type: "application/javascript+module", + content_base64: scriptBase64, + }, + ], + } + ); + + // Deploy the new version + await client.workers.scripts.deployments.create(PROD_WORKER_NAME, { + account_id: ACCOUNT_ID, + strategy: "percentage", + versions: [ + { + percentage: 100, + version_id: version.id, + }, + ], + }); + + console.log(`Successfully deployed version ${version.id} to production.`); +} + +deployToProduction(); +``` + +#### Deploy a preview for a feature branch + +Create a [preview deployment](#preview-deployments) by calling `applications.previews.create`. This automatically creates a temporary Worker and deploys your code: + +```typescript +import Cloudflare from "cloudflare"; +import fs from "fs"; + +const ACCOUNT_ID = process.env.CLOUDFLARE_ACCOUNT_ID; +const API_TOKEN = process.env.CLOUDFLARE_API_TOKEN; +const APP_ID = process.env.CLOUDFLARE_APP_ID; +const BRANCH_NAME = process.env.GIT_BRANCH_NAME; + +const client = new Cloudflare({ apiToken: API_TOKEN }); + +async function deployFeatureBranch() { + const scriptContent = fs.readFileSync("./dist/feature.mjs", "utf8"); + const scriptBase64 = Buffer.from(scriptContent).toString("base64"); + + // Deploy the feature branch + const featureDeployment = await client.workers.beta.applications.previews.create( + APP_ID, + { + account_id: ACCOUNT_ID, + main_module: "feature.mjs", + compatibility_date: "$today", + annotations: { + "workers/branch": BRANCH_NAME, + }, + modules: [ + { + name: "feature.mjs", + content_type: "application/javascript+module", + content_base64: scriptBase64, + }, + ], + } + ); + + console.log( + `Feature deployed to temporary worker: ${featureDeployment.worker_name}` + ); + + // Store the worker_id for cleanup when the PR is merged/closed + return featureDeployment.worker_id; +} + +async function cleanupFeatureBranch(ephemeralWorkerId: string) { + // Delete the temporary Worker when the PR is merged/closed + await client.workers.beta.workers.delete( + ephemeralWorkerId, + { + account_id: ACCOUNT_ID, + } + ); + console.log(`Cleaned up temporary worker: ${ephemeralWorkerId}`); +} + +// Example usage in your CI/CD pipeline +// const workerId = await deployFeatureBranch(); +// await cleanupFeatureBranch(workerId); +``` + + + + +This guide shows how to define your infrastructure using the [Cloudflare Terraform provider](https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs). This file is the source of truth for your application's permanent state. + +Install [Terraform](https://www.terraform.io/downloads). + +Create a `main.tf` file: + +```hcl +variable "account_id" { + description = "Your Cloudflare account ID" +} + +# Define the production Worker resource +resource "cloudflare_worker" "my_app_production_worker" { + account_id = var.account_id + name = "my-app-production" + observability = { + enabled = true + } +} + +# Define the preview Worker resource +# This Worker's settings are used as the template for all feature-branch deployments +resource "cloudflare_worker" "my_app_preview_worker" { + account_id = var.account_id + name = "my-app-preview" + # Configure preview-specific settings like test bindings here +} + +# Define the Application to link production and preview Workers +resource "cloudflare_worker_application" "my_app" { + account_id = var.account_id + name = "my-app" + + production_worker_id = cloudflare_worker.my_app_production_worker.id + preview_worker_id = cloudflare_worker.my_app_preview_worker.id +} + +# (Optional) Define the production deployment +# You can manage production deployments in Terraform or via CI/CD +resource "cloudflare_worker_version" "my_app_production_version" { + account_id = var.account_id + worker_id = cloudflare_worker.my_app_production_worker.id + + compatibility_date = "$today" + main_module = "prod-script.mjs" + modules = [ + { + name = "prod-script.mjs" + content_type = "application/javascript+module" + content_file = "path/to/prod-script.mjs" + } + ] +} + +resource "cloudflare_workers_deployment" "my_app_production_deployment" { + account_id = var.account_id + script_name = cloudflare_worker.my_app_production_worker.name + strategy = "percentage" + versions = [{ + percentage = 100 + version_id = cloudflare_worker_version.my_app_production_version.id + }] +} +``` + +Deploy your infrastructure: + +```bash +terraform init +terraform apply +``` + +**Note:** Temporary Workers created by [preview deployments](#preview-deployments) for feature branches should not be managed in this file. They are automatically created and cleaned up by your CI/CD pipeline. + + + + +## Using default environments with already deployed Workers + +If you have a Worker that was deployed before default environments were introduced, we recommend migrating your configuration to use the [`development`](#development-environment), [`preview`](#preview-environment), and [`production`](#production-environment) blocks. + +### Migrate your existing configuration + +To migrate your existing Worker to use default environments: + +1. Move your existing configuration into the `production` block in your [Wrangler configuration file](/workers/wrangler/configuration/). +2. Add `development` and `preview` blocks with the appropriate [bindings](/workers/runtime-apis/bindings/). +3. If you don't want to create separate resources for your [preview environment](#preview-environment), you can copy the resource names and IDs from your [production environment](#production-environment). + +**Before (existing configuration):** + + +```jsonc title="wrangler.jsonc" +{ + "name": "my-worker", + "compatibility_date": "$today", + "vars": { + "ENVIRONMENT": "production" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "abc123" + } + ], + "r2_buckets": [ + { + "binding": "MY_BUCKET", + "bucket_name": "my-bucket" + } + ] +} +``` + + +**After (with default environments):** + + +```jsonc title="wrangler.jsonc" +{ + "name": "my-worker", + "compatibility_date": "$today", + "development": { + "kv_namespaces": [ + { + "binding": "MY_KV" + } + ], + "r2_buckets": [ + { + "binding": "MY_BUCKET" + } + ] + }, + "preview": { + "vars": { + "ENVIRONMENT": "preview" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "abc123" + } + ], + "r2_buckets": [ + { + "binding": "MY_BUCKET", + "bucket_name": "my-bucket" + } + ] + }, + "production": { + "vars": { + "ENVIRONMENT": "production" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "abc123" + } + ], + "r2_buckets": [ + { + "binding": "MY_BUCKET", + "bucket_name": "my-bucket" + } + ] + } +} +``` + + +In this example: + +- **[Development environment](#development-environment):** Only defines binding types. [Miniflare](https://miniflare.dev/) will create local simulations when you run [`wrangler dev`](/workers/wrangler/commands/#dev). +- **[Preview environment](#preview-environment):** Uses the same resource IDs as production. All [preview deployments](#preview-deployments) will share these resources with your production deployment. +- **[Production environment](#production-environment):** Contains your original configuration with all resource IDs and [environment variables](/workers/configuration/environment-variables/). + +### Using separate resources for preview + +If you want to use separate resources for your [preview environment](#preview-environment), you can create new resources and specify their IDs: + + +```jsonc title="wrangler.jsonc" +{ + "preview": { + "vars": { + "ENVIRONMENT": "preview" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "preview-kv-id" + } + ], + "r2_buckets": [ + { + "binding": "MY_BUCKET", + "bucket_name": "my-preview-bucket" + } + ] + } +} +``` + + +You can create these resources using: + +- The [Cloudflare dashboard](https://dash.cloudflare.com) +- The [Wrangler CLI](/workers/wrangler/) (e.g., [`wrangler kv namespace create`](/kv/api/)) +- Letting [Wrangler](/workers/wrangler/) auto-provision them on your first [`wrangler deploy`](/workers/wrangler/commands/#deploy) + +## Using default environments with Wrangler environments + +We recommend using the default environments ([`development`](#development-environment), [`preview`](#preview-environment), and [`production`](#production-environment)) instead of [Wrangler environments](/workers/wrangler/configuration/#environments). However, if you're already using Wrangler environments, you can use both together. + +[Wrangler environments](/workers/wrangler/configuration/#environments) act as a template to create entirely separate copies of your Worker application as a long-lived environment. Each Wrangler environment creates a **separate Worker**, which means that each Wrangler environment Worker can have its own default environment settings. + +To use default environments with Wrangler environments, you nest [`development`](#development-environment), [`preview`](#preview-environment), and [`production`](#production-environment) configuration blocks within each Wrangler `env` block: + + +```jsonc title="wrangler.jsonc" +{ + "name": "my-worker", + "compatibility_date": "$today", + "env": { + "staging": { + "development": { + "kv_namespaces": [ + { + "binding": "MY_KV" + } + ] + }, + "preview": { + "vars": { + "ENVIRONMENT": "staging-preview" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "staging-preview-kv-id" + } + ] + }, + "production": { + "vars": { + "ENVIRONMENT": "staging-production" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "staging-production-kv-id" + } + ] + } + }, + "production": { + "development": { + "kv_namespaces": [ + { + "binding": "MY_KV" + } + ] + }, + "preview": { + "vars": { + "ENVIRONMENT": "production-preview" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "production-preview-kv-id" + } + ] + }, + "production": { + "vars": { + "ENVIRONMENT": "production-production" + }, + "kv_namespaces": [ + { + "binding": "MY_KV", + "id": "production-production-kv-id" + } + ] + } + } + } +} +``` + + +In this example: + +- **`staging` Wrangler environment:** Creates a separate Worker with its own [development](#development-environment), [preview](#preview-environment), and [production](#production-environment) settings. Deploy with `wrangler deploy --env staging`. +- **`production` Wrangler environment:** Creates another separate Worker with different default environment settings. Deploy with `wrangler deploy --env production`. + +Each Wrangler environment Worker operates independently with its own: + +- [Development environment](#development-environment) for local testing +- [Preview deployments](#preview-deployments) for testing branches +- [Production deployments](#production-deployments) for serving users