Environments
An environment is a separate, isolated instance of your Worker application. For example, you can have a staging and a production environment running simultaneously on Cloudflare.
Each environment has its own unique URL and can have different configuration — such as different resources that your bindings connect to, different environment variables, and different secrets. This isolation lets you test changes in one environment without affecting users in another.
You first define environments in Wrangler configuration, and then deploy them either manually or automatically through our Git integration.
You define environments in your Wrangler configuration file under the env field:
{ "name": "my-api", "main": "src/index.js", "compatibility_date": "2025-08-11",
// Environment-specific configurations "env": { "production": { "vars": { "ENVIRONMENT": "production", "API_ENDPOINT": "https://api.example.com", }, "d1_databases": [ { "binding": "DB", "database_name": "my-db-production", "database_id": "production-db-id", }, ], "routes": ["example.com/*"], }, "staging": { "vars": { "ENVIRONMENT": "staging", "API_ENDPOINT": "https://staging.example.com", }, "d1_databases": [ { "binding": "DB", "database_name": "my-db-staging", "database_id": "staging-db-id", }, ], }, },}name = "my-api"main = "src/index.js"compatibility_date = "2025-08-11"
[env.production]routes = [ "example.com/*" ]
[env.production.vars] ENVIRONMENT = "production" API_ENDPOINT = "https://api.example.com"
[[env.production.d1_databases]] binding = "DB" database_name = "my-db-production" database_id = "production-db-id"
[env.staging.vars]ENVIRONMENT = "staging"API_ENDPOINT = "https://staging.example.com"
[[env.staging.d1_databases]]binding = "DB"database_name = "my-db-staging"database_id = "staging-db-id"Complete configuration example with all binding types
This comprehensive example shows how to configure all available binding types across environments. The inline comments explain isolation requirements for each binding type.
{ "name": "my-worker", "main": "src/index.js", "compatibility_date": "2025-08-11",
// Environment-specific configurations "env": { "production": { "name": "my-worker-production", // Environment variables - can have different values per environment "vars": { "API_HOST": "example.com", "API_ACCOUNT_ID": "example_user", "SERVICE_X_DATA": { "URL": "service-x-api.prod.example", "MY_ID": 123, }, }, // Routes - must be unique (can't have same route for staging and production) "route": { "pattern": "example.org/*", "zone_name": "example.org", }, // Service bindings - target specific Worker environments // Use just the worker name to target its production environment "services": [ { "binding": "<BINDING_NAME>", "service": "<WORKER_NAME>", // Targets the production environment "entrypoint": "<ENTRYPOINT_NAME>", }, ], // KV namespaces - use different IDs for each environment to isolate data "kv_namespaces": [ { "binding": "<MY_NAMESPACE>", "id": "<PRODUCTION_KV_ID>" }, { "binding": "<BINDING_NAME2>", "id": "<PRODUCTION_NAMESPACE_ID2>", }, ], // D1 databases - use different IDs for each environment to isolate data "d1_databases": [ { "binding": "<BINDING_NAME>", "database_name": "<DATABASE_NAME>", "database_id": "<PRODUCTION_DATABASE_ID>" }, ], // R2 buckets - use different bucket names for each environment to isolate files "r2_buckets": [ { "binding": "<BINDING_NAME1>", "bucket_name": "<PRODUCTION_BUCKET_NAME>" }, { "binding": "<BINDING_NAME2>", "bucket_name": "<PRODUCTION_BUCKET_NAME2>", "jurisdiction": "eu", }, ], // Durable Objects - automatically isolated by environment "durable_objects": { "bindings": [ { "name": "<BINDING_NAME>", "class_name": "<CLASS_NAME>", }, { "name": "MY_DURABLE_OBJECT", "class_name": "MyDurableObjectClass", "script_name": "external-worker", // Will become "external-worker-production" "environment": "production", }, ], }, // Workflows - must have unique names (account-level resources) "workflows": [ { "name": "my-workflow-production", // Must be unique per environment "binding": "MY_WORKFLOW", "class_name": "MyWorkflow", }, ], // Queues - use different queue names for each environment to isolate messages "queues": { "producers": [ { "binding": "<BINDING_NAME>", "queue": "production-queue" "delivery_delay": 60, }, ], "consumers": [ { "queue": "production-queue", // Must match producer queue name "max_batch_size": 10, "max_batch_timeout": 30, "max_retries": 10, "dead_letter_queue": "production-queue-dlq", "max_concurrency": 5, "retry_delay": 120, }, ], }, // Analytics Engine - use different dataset names for each environment "analytics_engine_datasets": [ { "binding": "<BINDING_NAME>", "dataset": "<PRODUCTION_DATASET_NAME>" }, ], // Vectorize - must have unique index names per account "vectorize": [ { "binding": "<BINDING_NAME>", "index_name": "<PRODUCTION_INDEX_NAME>", // Must be unique per environment }, ], // AI binding - can be shared across environments "ai": { "binding": "AI", }, // Browser binding - can be shared across environments "browser": { "binding": "<BINDING_NAME>", }, // Email bindings - can use different addresses per environment "send_email": [ { "name": "<NAME_FOR_BINDING1>", }, { "name": "<NAME_FOR_BINDING2>", "destination_address": "<YOUR_EMAIL>@example.com", }, { "name": "<NAME_FOR_BINDING3>", "allowed_destination_addresses": [ "<YOUR_EMAIL>@example.com", "<YOUR_EMAIL2>@example.com", ], }, ], // Hyperdrive - use different IDs for each environment to isolate database connections "hyperdrive": [ { "binding": "<BINDING_NAME>", "id": "<PRODUCTION_HYPERDRIVE_ID>" }, ], // mTLS certificates - typically different per environment "mtls_certificates": [ { "binding": "<BINDING_NAME1>", "certificate_id": "<PRODUCTION_CERTIFICATE_ID>", }, ], // Version metadata - can be shared across environments "version_metadata": { "binding": "CF_VERSION_METADATA", }, // Tail consumers - automatically target the specified environment "tail_consumers": [ { "service": "tail-worker", }, ], "triggers": { "crons": ["* * * * *"], }, "observability": { "enabled": true, "head_sampling_rate": 0.1, }, }, "staging": { "name": "my-worker-staging", // Environment variables - can have different values per environment "vars": { "API_HOST": "staging.example.com", "API_ACCOUNT_ID": "staging_user", "SERVICE_X_DATA": { "URL": "service-x-api.dev.example", "MY_ID": 456, }, }, // Routes - must be unique "route": { "pattern": "staging.example.org/*", "zone_name": "example.org", }, // Service bindings - target specific Worker environments // Must append "-staging" to target a Worker's staging environment "services": [ { "binding": "<BINDING_NAME>", "service": "<WORKER_NAME>-staging", // Targets the staging environment "entrypoint": "<ENTRYPOINT_NAME>", }, ], // KV namespaces - SHOULD use different namespace IDs for isolation "kv_namespaces": [ { "binding": "<MY_NAMESPACE>", "id": "<STAGING_KV_ID>" }, { "binding": "<BINDING_NAME2>", "id": "<STAGING_NAMESPACE_ID2>", }, ], // D1 databases - SHOULD use different database IDs for isolation "d1_databases": [ { "binding": "<BINDING_NAME>", "database_name": "<STAGING_DATABASE_NAME>", "database_id": "<STAGING_DATABASE_ID>" "preview_database_id": "<PREVIEW_DATABASE_ID>", }, ], // R2 buckets - SHOULD use different bucket names for isolation "r2_buckets": [ { "binding": "<BINDING_NAME1>", "bucket_name": "<STAGING_BUCKET_NAME>" "preview_bucket_name": "<PREVIEW_BUCKET_NAME1>", }, { "binding": "<BINDING_NAME2>", "bucket_name": "<STAGING_BUCKET_NAME2>", "jurisdiction": "eu", }, ], // Durable Objects - automatically isolated by environment "durable_objects": { "bindings": [ { "name": "<BINDING_NAME>", "class_name": "<CLASS_NAME>", }, { "name": "MY_DURABLE_OBJECT", "class_name": "MyDurableObjectClass", "script_name": "external-worker", // Will become "external-worker-staging" "environment": "staging", }, ], }, // Workflows - must have unique names (account-level resources) "workflows": [ { "name": "my-workflow-staging", // Must be unique per environment "binding": "MY_WORKFLOW", "class_name": "MyWorkflow", }, ], // Queues - SHOULD use different queue names for isolation "queues": { "producers": [ { "binding": "<BINDING_NAME>", "queue": "staging-queue" "delivery_delay": 60, }, ], "consumers": [ { "queue": "staging-queue", // Must match producer queue name "max_batch_size": 5, "max_batch_timeout": 10, "max_retries": 5, "dead_letter_queue": "staging-queue-dlq", "max_concurrency": 2, "retry_delay": 60, }, ], }, // Analytics Engine - use different dataset names for each environment "analytics_engine_datasets": [ { "binding": "<BINDING_NAME>", "dataset": "<STAGING_DATASET_NAME>" }, ], // Vectorize - index names must be unique per account "vectorize": [ { "binding": "<BINDING_NAME>", "index_name": "<STAGING_INDEX_NAME>", // Must be unique per environment }, ], // AI binding - can be shared across environments "ai": { "binding": "AI", }, // Browser binding - can be shared across environments "browser": { "binding": "<BINDING_NAME>", }, // Email bindings - can use different addresses per environment "send_email": [ { "name": "<NAME_FOR_BINDING1>", }, { "name": "<NAME_FOR_BINDING2>", "destination_address": "test@example.com", // Test address for staging }, ], // Hyperdrive - SHOULD use different config IDs for database isolation "hyperdrive": [ { "binding": "<BINDING_NAME>", "id": "<STAGING_HYPERDRIVE_ID>" }, ], // mTLS certificates - typically different per environment "mtls_certificates": [ { "binding": "<BINDING_NAME1>", "certificate_id": "<STAGING_CERTIFICATE_ID>", }, ], // Version metadata - can be shared across environments "version_metadata": { "binding": "CF_VERSION_METADATA", }, // Tail consumers - automatically target the specified environment "tail_consumers": [ { "service": "tail-worker-staging", }, ], "triggers": { "crons": ["0 */6 * * *"], }, "observability": { "enabled": true, "head_sampling_rate": 1.0, }, }, },}name = "my-worker"main = "src/index.js"compatibility_date = "2025-08-11"
[env.production]name = "my-worker-production"
[env.production.vars] API_HOST = "example.com" API_ACCOUNT_ID = "example_user"
[env.production.vars.SERVICE_X_DATA] URL = "service-x-api.prod.example" MY_ID = 123
[env.production.route] pattern = "example.org/*" zone_name = "example.org"
[[env.production.services]] binding = "<BINDING_NAME>" service = "<WORKER_NAME>" entrypoint = "<ENTRYPOINT_NAME>"
[[env.production.kv_namespaces]] binding = "<MY_NAMESPACE>" id = "<PRODUCTION_KV_ID>"
[[env.production.kv_namespaces]] binding = "<BINDING_NAME2>" id = "<PRODUCTION_NAMESPACE_ID2>"
[[env.production.d1_databases]] binding = "<BINDING_NAME>" database_name = "<DATABASE_NAME>" database_id = "<PRODUCTION_DATABASE_ID>"
[[env.production.r2_buckets]] binding = "<BINDING_NAME1>" bucket_name = "<PRODUCTION_BUCKET_NAME>"
[[env.production.r2_buckets]] binding = "<BINDING_NAME2>" bucket_name = "<PRODUCTION_BUCKET_NAME2>" jurisdiction = "eu"
[[env.production.durable_objects.bindings]]name = "<BINDING_NAME>"class_name = "<CLASS_NAME>"
[[env.production.durable_objects.bindings]]name = "MY_DURABLE_OBJECT"class_name = "MyDurableObjectClass"script_name = "external-worker"environment = "production"
[[env.production.workflows]] name = "my-workflow-production" binding = "MY_WORKFLOW" class_name = "MyWorkflow"
[[env.production.queues.producers]]binding = "<BINDING_NAME>"queue = "production-queue"delivery_delay = 60
[[env.production.queues.consumers]]queue = "production-queue"max_batch_size = 10max_batch_timeout = 30max_retries = 10dead_letter_queue = "production-queue-dlq"max_concurrency = 5retry_delay = 120
[[env.production.analytics_engine_datasets]] binding = "<BINDING_NAME>" dataset = "<PRODUCTION_DATASET_NAME>"
[[env.production.vectorize]] binding = "<BINDING_NAME>" index_name = "<PRODUCTION_INDEX_NAME>"
[env.production.ai] binding = "AI"
[env.production.browser] binding = "<BINDING_NAME>"
[[env.production.send_email]] name = "<NAME_FOR_BINDING1>"
[[env.production.send_email]] name = "<NAME_FOR_BINDING2>" destination_address = "<YOUR_EMAIL>@example.com"
[[env.production.send_email]] name = "<NAME_FOR_BINDING3>" allowed_destination_addresses = [ "<YOUR_EMAIL>@example.com", "<YOUR_EMAIL2>@example.com" ]
[[env.production.hyperdrive]] binding = "<BINDING_NAME>" id = "<PRODUCTION_HYPERDRIVE_ID>"
[[env.production.mtls_certificates]] binding = "<BINDING_NAME1>" certificate_id = "<PRODUCTION_CERTIFICATE_ID>"
[env.production.version_metadata] binding = "CF_VERSION_METADATA"
[[env.production.tail_consumers]] service = "tail-worker"
[env.production.triggers] crons = [ "* * * * *" ]
[env.production.observability] enabled = true head_sampling_rate = 0.1
[env.staging]name = "my-worker-staging"
[env.staging.vars] API_HOST = "staging.example.com" API_ACCOUNT_ID = "staging_user"
[env.staging.vars.SERVICE_X_DATA] URL = "service-x-api.dev.example" MY_ID = 456
[env.staging.route] pattern = "staging.example.org/*" zone_name = "example.org"
[[env.staging.services]] binding = "<BINDING_NAME>" service = "<WORKER_NAME>-staging" entrypoint = "<ENTRYPOINT_NAME>"
[[env.staging.kv_namespaces]] binding = "<MY_NAMESPACE>" id = "<STAGING_KV_ID>"
[[env.staging.kv_namespaces]] binding = "<BINDING_NAME2>" id = "<STAGING_NAMESPACE_ID2>"
[[env.staging.d1_databases]] binding = "<BINDING_NAME>" database_name = "<STAGING_DATABASE_NAME>" database_id = "<STAGING_DATABASE_ID>" preview_database_id = "<PREVIEW_DATABASE_ID>"
[[env.staging.r2_buckets]] binding = "<BINDING_NAME1>" bucket_name = "<STAGING_BUCKET_NAME>" preview_bucket_name = "<PREVIEW_BUCKET_NAME1>"
[[env.staging.r2_buckets]] binding = "<BINDING_NAME2>" bucket_name = "<STAGING_BUCKET_NAME2>" jurisdiction = "eu"
[[env.staging.durable_objects.bindings]]name = "<BINDING_NAME>"class_name = "<CLASS_NAME>"
[[env.staging.durable_objects.bindings]]name = "MY_DURABLE_OBJECT"class_name = "MyDurableObjectClass"script_name = "external-worker"environment = "staging"
[[env.staging.workflows]] name = "my-workflow-staging" binding = "MY_WORKFLOW" class_name = "MyWorkflow"
[[env.staging.queues.producers]]binding = "<BINDING_NAME>"queue = "staging-queue"delivery_delay = 60
[[env.staging.queues.consumers]]queue = "staging-queue"max_batch_size = 5max_batch_timeout = 10max_retries = 5dead_letter_queue = "staging-queue-dlq"max_concurrency = 2retry_delay = 60
[[env.staging.analytics_engine_datasets]] binding = "<BINDING_NAME>" dataset = "<STAGING_DATASET_NAME>"
[[env.staging.vectorize]] binding = "<BINDING_NAME>" index_name = "<STAGING_INDEX_NAME>"
[env.staging.ai] binding = "AI"
[env.staging.browser] binding = "<BINDING_NAME>"
[[env.staging.send_email]] name = "<NAME_FOR_BINDING1>"
[[env.staging.send_email]] name = "<NAME_FOR_BINDING2>" destination_address = "test@example.com"
[[env.staging.hyperdrive]] binding = "<BINDING_NAME>" id = "<STAGING_HYPERDRIVE_ID>"
[[env.staging.mtls_certificates]] binding = "<BINDING_NAME1>" certificate_id = "<STAGING_CERTIFICATE_ID>"
[env.staging.version_metadata] binding = "CF_VERSION_METADATA"
[[env.staging.tail_consumers]] service = "tail-worker-staging"
[env.staging.triggers] crons = [ "0 */6 * * *" ]
[env.staging.observability] enabled = true head_sampling_rate = 1Because environments run as isolated copies of your application, all of your bindings and environment variables need to be redefined for each environment. This ensures complete isolation between environments — changes to resources in one environment won't affect another.
Each environment configuration must explicitly define:
- Environment variables (
vars) - All resource bindings (D1 databases, KV namespaces, R2 buckets, etc.)
- Secrets (managed separately via Wrangler or the dashboard)
- Any other configuration specific to that environment
All environments must be defined in your Wrangler configuration file. Once configured, you can deploy environments through two main workflows:
When you connect your repository to Cloudflare, Workers Builds automatically creates isolated preview environments for every pull request and can deploy specific branches to designated environments.
Every pull request automatically gets its own isolated environment. When you open a PR:
- Cloudflare automatically builds and deploys your code
- You receive two URLs:
- Preview URL: A unique URL for each commit -
https://<hash>-<worker-name>.<subdomain>.workers.dev - Branch URL: A stable URL that always shows the latest commit on that branch -
https://<branch-name>-<worker-name>.<subdomain>.workers.dev
- Preview URL: A unique URL for each commit -
These preview environments are perfect for:
- Testing changes before merging
- Sharing work with teammates for review
- Running integration tests against PR-specific endpoints
Deploy to specific environments using Wrangler:
npx wrangler deploy --env stagingyarn wrangler deploy --env stagingpnpm wrangler deploy --env stagingnpx wrangler deploy --env productionyarn wrangler deploy --env productionpnpm wrangler deploy --env productionWhen using the API, you don't create "environments" as a separate entity. Instead, each environment is deployed as its own Worker script. Cloudflare uses a naming convention where each environment becomes a Worker named <worker-name>-<environment-name>. For example, if your base Worker is named my-api:
- The production environment deploys as a Worker named
my-api - The staging environment deploys as a separate Worker named
my-api-staging
To deploy environments programmatically using the Cloudflare API, you upload each environment as a separate Worker script and specify tags to identify the relationship:
Deploy to production:
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/workers/scripts/my-api" \ -H "Authorization: Bearer {api_token}" \ -H "Content-Type: application/javascript" \ --data-binary "@worker.js" \ --form 'metadata={"main_module":"worker.js","tags":["service=my-api","environment=production"]}'Deploy to staging:
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/workers/scripts/my-api-staging" \ -H "Authorization: Bearer {api_token}" \ -H "Content-Type: application/javascript" \ --data-binary "@worker.js" \ --form 'metadata={"main_module":"worker.js","tags":["service=my-api","environment=staging"]}'The tags identify:
service: The base Worker name (same across all environments)environment: The specific environment being deployed
This approach means each environment runs as a completely separate Worker with its own isolated execution context, routes, and bindings. The tagging system helps Cloudflare understand the relationship between these separate Workers for management purposes.
Each binding type has different requirements for environment isolation. Understanding these patterns helps prevent data leakage between environments.
Use different id values to keep data separate between environments:
{ "env": { "production": { "kv_namespaces": [ { "binding": "<MY_NAMESPACE>", "id": "<PRODUCTION_KV_ID>", }, ], }, "staging": { "kv_namespaces": [ { "binding": "<MY_NAMESPACE>", "id": "<STAGING_KV_ID>", // Warning: Using the production ID would share data }, ], }, },}[[env.production.kv_namespaces]]binding = "<MY_NAMESPACE>"id = "<PRODUCTION_KV_ID>"
[[env.staging.kv_namespaces]]binding = "<MY_NAMESPACE>"id = "<STAGING_KV_ID>"Use different database_id values to maintain separate data stores:
{ "env": { "production": { "d1_databases": [ { "binding": "<BINDING_NAME>", "database_name": "<DATABASE_NAME>", "database_id": "<PRODUCTION_DATABASE_ID>", }, ], }, "staging": { "d1_databases": [ { "binding": "<BINDING_NAME>", "database_name": "<STAGING_DATABASE_NAME>", "database_id": "<STAGING_DATABASE_ID>", // Warning: Using the production ID would share the database }, ], }, },}[[env.production.d1_databases]]binding = "<BINDING_NAME>"database_name = "<DATABASE_NAME>"database_id = "<PRODUCTION_DATABASE_ID>"
[[env.staging.d1_databases]]binding = "<BINDING_NAME>"database_name = "<STAGING_DATABASE_NAME>"database_id = "<STAGING_DATABASE_ID>"Use different bucket_name values to use different storage buckets for each environment:
{ "env": { "production": { "r2_buckets": [ { "binding": "<BINDING_NAME1>", "bucket_name": "<PRODUCTION_BUCKET_NAME>", }, ], }, "staging": { "r2_buckets": [ { "binding": "<BINDING_NAME1>", "bucket_name": "<STAGING_BUCKET_NAME>", // Warning: Using the production bucket would share files }, ], }, },}[[env.production.r2_buckets]]binding = "<BINDING_NAME1>"bucket_name = "<PRODUCTION_BUCKET_NAME>"
[[env.staging.r2_buckets]]binding = "<BINDING_NAME1>"bucket_name = "<STAGING_BUCKET_NAME>"Use different queue names to prevent message mixing:
{ "env": { "production": { "queues": { "producers": [ { "binding": "<BINDING_NAME>", "queue": "production-queue", }, ], }, }, "staging": { "queues": { "producers": [ { "binding": "<BINDING_NAME>", "queue": "staging-queue", // Warning: Using the production queue would mix messages }, ], }, }, },}[[env.production.queues.producers]]binding = "<BINDING_NAME>"queue = "production-queue"
[[env.staging.queues.producers]]binding = "<BINDING_NAME>"queue = "staging-queue"Use different id values to connect to separate databases:
{ "env": { "production": { "hyperdrive": [ { "binding": "<BINDING_NAME>", "id": "<PRODUCTION_HYPERDRIVE_ID>", }, ], }, "staging": { "hyperdrive": [ { "binding": "<BINDING_NAME>", "id": "<STAGING_HYPERDRIVE_ID>", // Warning: Using the production ID would connect to production database }, ], }, },}[[env.production.hyperdrive]]binding = "<BINDING_NAME>"id = "<PRODUCTION_HYPERDRIVE_ID>"
[[env.staging.hyperdrive]]binding = "<BINDING_NAME>"id = "<STAGING_HYPERDRIVE_ID>"Use different dataset names to keep metrics separate:
{ "env": { "production": { "analytics_engine_datasets": [ { "binding": "<BINDING_NAME>", "dataset": "<PRODUCTION_DATASET_NAME>", }, ], }, "staging": { "analytics_engine_datasets": [ { "binding": "<BINDING_NAME>", "dataset": "<STAGING_DATASET_NAME>", // Warning: Using the production dataset would mix metrics }, ], }, },}[[env.production.analytics_engine_datasets]]binding = "<BINDING_NAME>"dataset = "<PRODUCTION_DATASET_NAME>"
[[env.staging.analytics_engine_datasets]]binding = "<BINDING_NAME>"dataset = "<STAGING_DATASET_NAME>"Must use unique pattern values. Each URL pattern can only point to one Worker.
{ "env": { "production": { "route": { "pattern": "example.org/*", // Must be unique across all Workers "zone_name": "example.org", }, }, "staging": { "route": { "pattern": "staging.example.org/*", // Must be unique across all Workers "zone_name": "example.org", }, }, },}[env.production.route]pattern = "example.org/*"zone_name = "example.org"
[env.staging.route]pattern = "staging.example.org/*"zone_name = "example.org"Must specify the target environment by appending the environment name to the service field.
{ "env": { "production": { "services": [ { "binding": "<BINDING_NAME>", "service": "<WORKER_NAME>", // Targets production environment of the Worker }, ], }, "staging": { "services": [ { "binding": "<BINDING_NAME>", "service": "<WORKER_NAME>-staging", // Must append environment name }, ], }, },}[[env.production.services]]binding = "<BINDING_NAME>"service = "<WORKER_NAME>"
[[env.staging.services]]binding = "<BINDING_NAME>"service = "<WORKER_NAME>-staging"Must have unique name values. Workflows are account-level resources that environments reference by name.
{ "env": { "production": { "workflows": [ { "name": "my-workflow-production", // Must be unique per environment "binding": "MY_WORKFLOW", "class_name": "MyWorkflow", }, ], }, "staging": { "workflows": [ { "name": "my-workflow-staging", // Must be unique per environment "binding": "MY_WORKFLOW", "class_name": "MyWorkflow", }, ], }, },}[[env.production.workflows]]name = "my-workflow-production"binding = "MY_WORKFLOW"class_name = "MyWorkflow"
[[env.staging.workflows]]name = "my-workflow-staging"binding = "MY_WORKFLOW"class_name = "MyWorkflow"Must have unique index_name values per account. Cannot be changed after creation.
{ "env": { "production": { "vectorize": [ { "binding": "<BINDING_NAME>", "index_name": "<PRODUCTION_INDEX_NAME>", // Must be unique per environment }, ], }, "staging": { "vectorize": [ { "binding": "<BINDING_NAME>", "index_name": "<STAGING_INDEX_NAME>", // Must be unique per environment }, ], }, },}[[env.production.vectorize]]binding = "<BINDING_NAME>"index_name = "<PRODUCTION_INDEX_NAME>"
[[env.staging.vectorize]]binding = "<BINDING_NAME>"index_name = "<STAGING_INDEX_NAME>"Automatically isolated. Each environment gets its own instances with separate storage:
{ "durable_objects": { "bindings": [ { "name": "RATE_LIMITER", "class_name": "RateLimiter", // Automatically isolated per environment }, ], },}[[durable_objects.bindings]]name = "RATE_LIMITER"class_name = "RateLimiter"Automatically isolated. Route logs to the specified Worker:
{ "env": { "production": { "tail_consumers": [ { "service": "log-worker", }, ], }, "staging": { "tail_consumers": [ { "service": "log-worker-staging", }, ], }, },}[[env.production.tail_consumers]]service = "log-worker"
[[env.staging.tail_consumers]]service = "log-worker-staging"Can share configuration. Provides access to the same AI models across all environments:
{ "ai": { "binding": "AI", },}[ai]binding = "AI"Can share configuration. Provides access to the same browser rendering service:
{ "browser": { "binding": "<BINDING_NAME>", },}[browser]binding = "<BINDING_NAME>"Can share configuration. Can use the same certificate or different ones per environment:
{ "env": { "production": { "mtls_certificates": [ { "binding": "<BINDING_NAME1>", "certificate_id": "<PRODUCTION_CERTIFICATE_ID>", }, ], }, "staging": { "mtls_certificates": [ { "binding": "<BINDING_NAME1>", "certificate_id": "<STAGING_CERTIFICATE_ID>", }, ], }, },}[[env.production.mtls_certificates]]binding = "<BINDING_NAME1>"certificate_id = "<PRODUCTION_CERTIFICATE_ID>"
[[env.staging.mtls_certificates]]binding = "<BINDING_NAME1>"certificate_id = "<STAGING_CERTIFICATE_ID>"Can share configuration. Provides Worker version information:
{ "version_metadata": { "binding": "CF_VERSION_METADATA", },}[version_metadata]binding = "CF_VERSION_METADATA"Was this helpful?
- Resources
- API
- New to Cloudflare?
- Products
- Sponsorships
- Open Source
- Support
- Help Center
- System Status
- Compliance
- GDPR
- Company
- cloudflare.com
- Our team
- Careers
- © 2025 Cloudflare, Inc.
- Privacy Policy
- Terms of Use
- Report Security Issues
- Trademark