Source: https://architectingoncloudflare.com/chapter-22

# Chapter 22: Security, Compliance, and Deployment

*How do we meet security and compliance requirements?*

---

Security requirements kill platform choices. An engineering team can build features on any modern platform, but enterprise security (compliance certifications, data residency, audit trails) narrows the options drastically. Assess the controls and agreements for the specific services and data flows the application will use.

This chapter covers decisions that make enterprise adoption possible: how the isolate model shapes your security posture, authentication patterns, compliance constraints, and how to test and control production deployments.

## The security model of isolates

Understanding the isolate model's security implications shapes every decision on the platform.

Workers run in V8 isolates, the same technology that keeps browser tabs from reading each other's memory. This has been battle-tested across billions of browser instances daily.

Workers remove the operating-system administration and process access of a traditional server, but an isolate can serve several concurrent requests and be reused for later ones. Its global memory is not cleared at each request boundary. Keep request-specific secrets and user data out of shared globals; isolation between deployed workloads does not separate users served by the same code.

Secrets and bindings reach your code through the environment object. That avoids distributing connection credentials through configuration files, but compromised application code can still use every capability you grant it. Scope bindings and secrets to the Worker's actual responsibilities.

### What isolates don't protect

> **What Isolates Don't Protect**
>
> The V8 isolate model protects you from other customers' code, not from your own mistakes. Isolates provide no protection against application vulnerabilities, misconfigured bindings, or accidentally persisting sensitive data to storage services.


Understanding the security model means understanding its boundaries. Isolates separate workloads, but do not address several threat categories that remain your responsibility.

Isolates don't protect against your own code. If your Worker exfiltrates data through legitimate network calls, whether through supply chain compromise, logic bug, or malicious insider code, the isolate model is irrelevant. The code runs with the permissions you've granted.

Isolates don't protect against misconfiguration. Overly permissive CORS headers, bindings that grant production data access from staging environments, secrets accidentally logged: these are architectural failures, not runtime vulnerabilities. The platform can't save you from yourself.

Isolates don't prevent persisting sensitive data inappropriately. Sensitive information written to KV, D1, or Durable Objects persists according to your application's retention policy. Cache authentication tokens in KV without TTLs and those credentials outlive the request that created them.

The isolate model shrinks your attack surface. It doesn't eliminate the need for secure coding practices, careful configuration management, and deliberate data handling. Think of it as defence in depth: the platform provides multiple layers, but you're responsible for others.

### Defence in depth: what the platform provides

Cloudflare combines runtime isolation, sandboxing and restrictions on host access to contain untrusted code. These controls reduce the scope of a runtime compromise; they do not make platform vulnerabilities impossible or restrict a compromised application from using its legitimate bindings.

The isolate is one boundary inside another. Cloudflare also sandboxes the runtime process, blocking direct access to the host filesystem and external network. Processes outside that sandbox mediate external access. This helps contain a runtime compromise, while the application's own permitted bindings and outbound calls still need appropriate controls.

Workers also limits timing facilities that can support side-channel attacks. `Date.now()` and `performance.now()` advance after I/O rather than measuring CPU execution continuously. This is why timing a synchronous block in production cannot replace local CPU profiling.

For an architectural review, separate three questions: which platform boundary contains the code, which resources its bindings and credentials permit it to reach, and which users the application authorises to perform each operation. Runtime isolation answers only the first. Review Cloudflare's documented security model for the current implementation details rather than making application guarantees depend on a particular sandbox mechanism or patch-time claim.

## Authentication at the edge

Rejecting invalid credentials at the edge protects backend capacity as well as reducing unnecessary work. Authentication still requires the same care over token validation, expiry and revocation.

When a Worker can validate a token locally against a trusted cached key, it can reject an invalid request before invoking a backend. Key retrieval, revocation checks and session lookups may still require remote work. Compare the actual authentication paths: an application server can also validate a JWT without querying a database.

If ten percent of your traffic fails authentication (expired tokens, malformed requests, bot probes), edge validation prevents that ten percent from reaching your backend. For an application serving ten million requests daily, that's one million backend requests eliminated. Estimate the saving from the backend work those rejected requests would actually have performed.

### Choosing an authentication strategy

Cloudflare supports multiple authentication patterns, each suited to different scenarios. The choice matters more than implementation details.

**Cloudflare Access** delegates authentication to an identity provider and issues an application token. Your Worker must validate the `Cf-Access-Jwt-Assertion` token, including its signature, issuer, audience and expiry, before trusting identity claims. Protect every route that can reach the application so an alternative hostname cannot bypass Access. Access handles the identity-provider integration; your application still decides what the authenticated user may do.

Keep provisioned Access applications and runtime validation aligned. Each Access application has its own [audience identifier](https://developers.cloudflare.com/cloudflare-one/access-controls/applications/http-apps/authorization-cookie/validating-json/); a token valid for one application should not gain access to another application's routes merely because both use the same identity provider. Chapter 5 separates local token tests from deployed checks of that route coverage.

The architectural benefit is separation of concerns. Access handles the complexity of SAML, OIDC, and identity provider quirks. You avoid reimplementing federated authentication, which is notoriously easy to get subtly wrong.

Access excels when you have existing identity infrastructure, when you're protecting internal tools or employee-facing applications, or when compliance requires audit trails tied to corporate identity. Less suited to consumer applications where users don't have accounts in your identity provider.

**Custom JWT validation** makes sense when building consumer applications with your own user database, when you need fine-grained claims beyond basic identity, or when building API-first services where federated identity doesn't fit. You control token format, claims structure, and validation logic. The tradeoff: you handle token issuance, refresh flows, and revocation.

JWT validation at the edge is straightforward; libraries handle the cryptography. The architectural decisions matter more than the code. What claims do you need? How long should tokens live? How do you handle refresh? These questions have the same answers anywhere; edge location doesn't change token design principles.

**API keys** suit service-to-service communication where simplicity outweighs sophistication. Generate a random key, hash it for storage, validate on each request. API keys work well for tracking usage by client, building developer APIs with usage tiers, or when the calling service can securely store credentials.

The decision framework:

| Scenario | Recommended Approach |
|----------|---------------------|
| Internal tools, employee access | Cloudflare Access |
| Consumer application, own user database | Custom JWT |
| B2B SaaS with SSO requirements | Cloudflare Access or SAML integration |
| Public API with developer keys | API keys with rate limiting |
| Service-to-service, high trust | API keys or mutual TLS |
| Mixed: employees and external users | Access for employees, JWT for external |

### Where session state lives

Choose session storage by the state it must preserve and the decisions it must enforce. A session might be a token with metadata (KV), queryable user state (D1), or a coordination point across concurrent requests (Durable Objects).

**KV** suits session metadata only when delayed visibility and revocation are acceptable. Cached values, including cached misses, can remain stale across locations; the risk is not limited to users changing continents. Keep token lifetimes and revocation requirements explicit before using an eventually consistent session store.

The limitation is query capability. You cannot ask KV "find all sessions for user X" or "count active sessions." For single-session policies or displaying active sessions to users, KV's key-value model doesn't help.

**D1** suits session data requiring relational queries, such as listing or revoking a user's sessions. Reads go to the primary unless the application uses read replication through the Sessions API. For decisions requiring current revocation state, choose the read path deliberately: asynchronous replicas do not become globally current merely because a write succeeded.

**Durable Objects** suit sessions that coordinate connections or concurrent actions. An object provides a place to serialise decisions for one session or user. Event handlers can interleave at asynchronous boundaries, so the application must still use the storage and concurrency guarantees correctly.

Choose from the session’s responsibilities: KV for metadata whose stale visibility is acceptable, D1 for queryable records and transactional changes, or Durable Objects for active coordination. Identity proof and current permission remain separate checks whichever store you choose.

## Secrets management

Choose secret storage by its consumers, administration boundary and rotation requirements. Worker-specific secrets, account-level Secrets Store bindings and external services support different operating models.

### Wrangler secrets: simple and usually sufficient

Wrangler secrets are encrypted at rest and made available to the Worker at runtime without putting their values in the checked-in configuration. Application code can still expose them through logs, responses or outbound requests. Treat access to the secret and authority to deploy that code as access to the protected resource.

The limitation: Wrangler secrets are static. Changing a secret requires redeployment. For most applications, this is irrelevant; you change secrets rarely, and redeployment takes seconds.

Worker-specific secrets are a reasonable starting point when each application owns its credentials. Sharing a credential across several Workers creates a separate administration and rotation problem.

### When a shared secrets service matters

[Secrets Store](https://developers.cloudflare.com/secrets-store/), in open beta, stores account-level secrets that supported consumers can reuse. Its user roles separate secret administration from permission to bind a secret to a Worker. API tokens use a different permission model: binding requires Account Secrets Store Edit, and the secret must permit the `workers` scope. Include that authority in the CI credential review. The Worker retrieves a value asynchronously through its binding. This suits shared credentials whose ownership should sit outside one application's deployment configuration.

It does not by itself establish a short-lived credential issuance or automatic rotation workflow. For those requirements, or a shared source across several cloud platforms, compare an external secrets service with the native option.

Compare those capabilities with the service's access controls, availability and cache behaviour. Fetching a secret on every request can add a dependency to the critical path; caching it changes how quickly rotation and revocation take effect. Define those windows explicitly.

Compliance labels or company size do not decide the architecture. Identify the required control and evidence, then select a service that supplies them. Keep the simpler arrangement when it meets the requirement.

### Rotation without downtime

When secrets must rotate without interrupting service, support overlapping validity by keeping both old and new keys valid during the transition. Your validation logic accepts either key, allowing you to set the new key, deploy with both valid, wait for all clients to update, and finally remove the old key.

This dual-key period prevents rotation from causing failures. The pattern is simple but requires designing for it from the start; retrofitting dual-key support onto a system assuming single keys is substantially more work than building it in initially.

### Scannable Cloudflare API tokens

Scannable token formats and secret scanning help detect exposed credentials. Treat detection as a recovery aid: keep tokens narrowly scoped, restrict where they are stored and rotate them after suspected exposure.

### Scope deployment authority to the Worker

Workers permissions separate investigation, code review, deployment, and deletion. Metadata Read-Only permits settings and observability access without code access; Content Read-Only includes code inspection; Editor permits updates and deployments; Admin adds deletion. Apply these roles to individual Workers for teammates, agents, and CI tokens. Durable Objects inherit the permissions of the Worker that implements them.

Give a deployment pipeline Editor access to the Workers it owns rather than account-wide administration. Keep lifecycle management separate when the pipeline does not need to delete resources. Read-only investigation roles can reduce an agent's authority, but logs and traces may still contain sensitive application data.

Deployment authority also carries indirect data access. An Editor can deploy code using the Worker's existing KV, D1, and R2 bindings without separate direct permissions on those resources. Scoping a token to one Worker limits which code it can change; it does not prevent that code from accessing production data already bound to the Worker. Review deployment permissions and resource bindings together.

### Choose the account boundary

Separate accounts can give teams distinct administration and billing boundaries. Use that separation when broad account permissions or shared ownership would otherwise let one team's changes affect another. Keep resources together when the same team owns them and the additional access, deployment and integration work of multiple accounts buys little isolation.

[Self-service users can create standalone Free accounts](https://developers.cloudflare.com/changelog/post/2026-08-04-free-dashboard-button/); Enterprise accounts under an existing contract still require the account team. [Organizations](https://developers.cloudflare.com/fundamentals/organizations/for-enterprise/) is generally available for Enterprise customers and eligible service-provider partners, grouping accounts for shared administration and visibility. Enterprise organisations use a flat account hierarchy; partner organisations can support nested customer structures. Organization Super Administrators have implicit access across the accounts they govern. Check the available roles and product-specific policy-sharing support before treating this as a complete governance layer. Keep access for a team responsible for only some accounts at the account level.

## Compliance as architecture

Compliance certifications prove Cloudflare's infrastructure meets standards, but your architecture determines whether your use of that infrastructure meets standards. The platform is eligible; you make it compliant.

Cloudflare maintains SOC 2 Type II, ISO 27001, GDPR compliance documentation, HIPAA eligibility with Business Associate Agreements, and PCI DSS compliance. Your account team can provide attestation documents for procurement.

What matters more: understanding how compliance requirements translate into architectural decisions. Listing certifications doesn't help you build compliant systems.

### GDPR: design for deletion

GDPR grants data subjects specific rights. The architectural challenge: these rights assume you can find all data about a person, and most systems aren't designed for that.

An erasure request can span D1 tables, R2 objects, KV entries and Durable Object storage. Build an inventory that supports the applicable erasure and retention rules, including lawful retention exceptions and backup treatment. Restoration must not silently reintroduce data that should remain erased.

Design your data model around a consistent user identifier that appears everywhere. When a deletion request arrives, you need a tractable query ("find everything with user_id X"), not an archaeological expedition through heterogeneous storage systems. D1 foreign keys help within a database, but deletion across D1, R2, and KV requires application logic you must design intentionally.

The right to access means users can request all data you hold. Same architectural principle: if you cannot enumerate all storage locations for a user, you cannot fulfil access requests accurately.

Data minimisation is an architectural philosophy, not a technical control. Before storing something, ask whether you actually need it. Cloudflare's storage makes keeping data easy and cheap; compliance requires discipline about what to keep. Data you don't store is data you don't need to protect, export, or delete.

### Data residency: performance tradeoffs

Jurisdictional restrictions that keep data in specific regions carry consequences beyond compliance checkboxes.

Restricting a Durable Object to the EU keeps its execution within that jurisdiction. A caller in Asia still crosses the intercontinental network to reach that authority. Measure the resulting latency for the actual users and dependencies; a residency boundary does not imply either a fixed penalty or no penalty for callers inside it.

The same logic applies to the other jurisdictions Durable Objects support. Alongside `eu`, you can pin an object to `us` (compute and storage held inside the United States) or `fedramp` (FedRAMP-authorised facilities). Keeping an object within the US may align with its users, but does not eliminate network latency or service charges. A jurisdiction restriction can place some callers farther from the object's authority. Pick the jurisdiction your obligations actually require, not the broadest one available.

The decision framework for jurisdictional restrictions:

| Data Type | Restriction Typically Needed? | Performance Impact |
|-----------|------------------------------|-------------------|
| Personal data covered by GDPR | Assess transfer rules and contractual commitments; EU-only storage is not a blanket GDPR requirement | Depends on where authorised users and dependencies are located |
| US data under a residency clause | Yes, if contractually required | Depends on caller and dependency locations |
| Financial records for EU entity | Assess the applicable obligations | Test against the transaction latency objective |
| Real-time game state | Rarely | Severe; latency matters |
| User preferences | Assess what the preferences reveal and the applicable commitments | Depends on the chosen storage location |

Distinguish D1 location hints from jurisdiction restrictions. A hint guides placement without guaranteeing it. A jurisdiction restriction constrains the database's compute and storage, including read replicas, to that jurisdiction. It does not itself constrain where the calling Worker executes.

Queues also supports jurisdiction restrictions for message storage and queue-service processing. The producer and consumer Workers remain separate location decisions, and the dead-letter queue must match the source jurisdiction. Chapter 9 covers the creation-time constraint and migration consequence. Include retries, logs and downstream calls when tracing the complete data path.

### Data localization suite: enterprise controls

For enterprises with stringent data sovereignty requirements, Cloudflare offers the Data Localization Suite as an Enterprise add-on. The suite provides three independent controls that layer together depending on your compliance needs.

**Regional Services** controls where TLS termination and request processing occur. When you configure a hostname for EU Regional Services, requests from anywhere in the world route to EU data centres before decryption. A user in Singapore connecting to your EU-regionalised hostname experiences their traffic routed across the globe to Europe before Cloudflare decrypts and processes it. Layer 3/4 DDoS mitigation still happens globally, while the covered application-layer processing occurs within the specified region. For Workers, this hostname control does not regionalise every trigger or outbound subrequest, nor the distribution of deployed code and secrets; check the [Workers-specific limitations](https://developers.cloudflare.com/data-localization/how-to/workers/).

**Geo Key Manager** controls where your TLS private keys are stored. By default, Cloudflare distributes encrypted keys to all data centres for local TLS termination. With Geo Key Manager, keys stay within specified regions. Data centres outside those regions must request session keys from key-holding data centres, adding latency to connection establishment. This latency only affects the initial TLS handshake; subsequent requests and session resumption don't require key server access. The trade-off is meaningful: a user in Asia connecting to a site with EU-only keys pays an intercontinental round-trip on first connection.

**Customer Metadata Boundary** controls storage of covered Customer Logs, with product and dataset exceptions. Dashboard and API access can depend on where the session is routed, rather than simply the operator's physical location; out-of-region access changes viewing permissions without relocating stored logs. Check [dataset compatibility](https://developers.cloudflare.com/data-localization/metadata-boundary/logpush-datasets/) and verify delivery after enabling CMB: an unsupported regional dataset can stop Logpush delivery without an error notification.

These controls are independent. You might use Regional Services without Geo Key Manager, or Geo Key Manager without Customer Metadata Boundary. Each adds compliance capability at a cost: Regional Services adds latency for non-regional users; Geo Key Manager adds connection establishment latency; Customer Metadata Boundary restricts analytics access. Understand each trade-off before enabling.

A boundary outside the managed region list may call for a custom region arranged through the account team. Check the ingress design before relying on it: custom regions support Regionalized Spectrum Applications and Regionalized IP Bindings, but do not support Regional Hostnames. The required geography can therefore change how traffic reaches the application.

The available jurisdictions and compatible products differ among these controls. Check their intersection for the application's actual hostnames, storage, logs and dependency calls before making a residency commitment. A control over one stage of a request does not establish the location of every later data flow.

### HIPAA: eligibility is not compliance

> **Platform Certification Is Not Application Compliance**
>
> Cloudflare's SOC 2 certification or HIPAA BAA covers their infrastructure, not your application. You remain responsible for access controls, audit logging, data handling, and all other application-level compliance requirements.


HIPAA requires a Business Associate Agreement before storing protected health information. Cloudflare offers BAAs for enterprise accounts. But a BAA doesn't make your application HIPAA-compliant; it makes Cloudflare's infrastructure eligible for use in a compliant application.

Your architecture must still implement access controls, audit logging, appropriate encryption and minimum necessary access. Confirm that the agreement covers the specific Cloudflare services and data flows you intend to use; eligibility for one service does not establish eligibility for the whole architecture.

A BAA is one prerequisite. The remaining work is to map the application's data flows and controls to the obligations, including logging, support access, retention and deletion.

### PCI: scope reduction is the strategy

Processor-hosted payment collection and tokenisation can reduce PCI scope by keeping card numbers out of the application. Confirm that the actual integration prevents the application from recovering the underlying number and meets the relevant scope criteria. A value called a token does not, by its format alone, establish that boundary.

If you must handle card data directly, requirements escalate significantly: encryption in transit, encryption at rest, access logging, key rotation, vulnerability management, penetration testing, and more. Cloudflare's infrastructure provides some of these controls, but you're responsible for application-level implementation.

Document the remaining application responsibilities with the payment provider. Scope depends on the collection flow and integration, not just where the final token is stored.

### What compliance can't easily achieve

Some requirements depend on controls the selected Cloudflare service does not expose. Identify those gaps before committing to the deployment.

**Cross-region audit logging** requires intentional design. Logs from Workers don't automatically aggregate into a central, tamper-proof audit store. For comprehensive audit trails, build the aggregation and ship logs to a centralised system via Logpush or application-level logging.

**Fine-grained access control within a Worker** is your responsibility. If multiple teams share a Worker and compliance requires tracking which team accessed which data, that's application logic you implement, not platform capability you configure.

[Audit Logs v2](https://developers.cloudflare.com/changelog/post/2026-10-13-audit-logs-v2-view-actions/) records read activity for supported management endpoints as `view` actions. The dashboard hides these by default, while API and Logpush access includes them. Include relevant reads when investigating credential or configuration exposure, but keep application audit records: platform management logs do not capture every customer-data read.

**Infrastructure you control** is required by some compliance frameworks. Edge compute is, by definition, someone else's infrastructure. If compliance mandates that all processing occur on hardware you own, serverless platforms (Cloudflare included) don't fit.

## Deployment as hypothesis testing

A deployment without predefined success criteria isn't a gradual rollout; it's a gradual hope that drifts until reality intrudes. Define what "working" means before you deploy, or you'll discover what "broken" means from your users.

### From provisioned resources to deployed bindings

A release can run the right code against the wrong database. Assign ownership of resources and deployment configuration before choosing the pipeline. Cloudflare supports [several infrastructure-as-code approaches](https://developers.cloudflare.com/workers/platform/infrastructure-as-code/); one tool can manage the whole deployment, or a provisioning system can hand resource identifiers to the application release process. With split ownership, specify which system may change each field so a later infrastructure run does not undo an application release.

Suppose Terraform provisions a staging D1 database and the application pipeline deploys its Worker. The provisioning run produces the database identifier; the release process consumes it as the `DB` binding and checks the resolved account, environment and resource before deployment. Keep that resolved configuration with the release evidence. Whether the project generates a Wrangler file or evaluates typed configuration, a reviewer needs to see which database the code will reach.

Local development can use disposable resources without provisioning the remote stack. A release must stop when required identifiers are missing or invalid, rather than substituting local defaults. A readable outputs file is insufficient: it may describe another environment or a database that has since been replaced. Refresh the handoff from the intended infrastructure state and verify its targets. Rehearse a missing output and a stale identifier alongside the successful deployment.

### Code rollback and state rollback

Workers versions let a deployment route traffic to retained code versions and change their allocation without rebuilding the application. This makes gradual exposure and code rollback practical parts of normal deployment.

The previous version's existence does not reverse writes, schema changes or calls to external systems. Before rolling back, check that the older code can read the current data and tolerate work started by the newer version. Use compatible schema changes and versioned messages when old and new code will coexist.

### Defining success criteria

Before deploying, establish measurable criteria. Write these down before you deploy, not while staring at ambiguous metrics trying to decide whether the deployment succeeded.

**Error rate threshold:** "Error rate must not increase by more than 0.1% compared to the previous version." Be specific about what counts as an error: 5xx responses only, or also 4xx that indicate bugs? Over what time window: instantaneous, or averaged over five minutes?

**Latency threshold:** "P99 latency must remain below 200ms." Choose the percentile that matters for your application. P50 hides tail latency issues that affect your most complex requests or unluckiest users. P99 or P99.9 reveals them.

**Business metrics:** "Conversion rate must not decrease." "API success rate must stay above 99.9%." Connect deployment health to outcomes that matter. A deployment passing technical metrics but tanking business metrics isn't successful.

**No new error types:** "No error messages appearing that were not present in the previous version." New errors often indicate new bugs. This criterion catches issues that might not increase error rate significantly but indicate problems.

### Exposure, observation and rollback

Choose the first allocation by the harm a defect could cause and the traffic needed to observe it. A small percentage of a high-volume API can give useful evidence quickly; the same percentage on a low-volume system may miss the relevant paths entirely.

Keep each stage long enough to exercise meaningful behaviour: concurrent writes, scheduled jobs, a traffic peak or a complete business process. Request counts alone do not expose time-dependent failures.

Define rollback triggers before deployment using the baseline and the change's risks. Compare new and old versions where possible, including correctness and business outcomes as well as error rate and latency. A normal background 5xx in the first hundred requests is not automatically evidence against the release, while one incorrect payment can justify immediate intervention.

When a trigger fires, use the prepared recovery path. Confirm code and data compatibility before routing back, and escalate when recovery needs more than a code version change.

### Environment progression

Maintain separate environments: development, staging, production. Deploy to staging first. Run automated tests against staging. Verify manually. Only then deploy to production with gradual rollout.

The binding model makes environment separation clean. Staging and production Workers are identical artifacts with different bindings. Staging points to staging databases, staging KV namespaces, staging Durable Object namespaces. Production points to production resources.

What should differ between environments? Data sources must differ; you don't want staging tests modifying production data. Code paths should not differ. Avoid conditional logic based on environment that means staging doesn't test production behaviour.

Feature flags provide safer conditional behaviour than environment checks. A feature flag tested in staging behaves identically in production; an environment check by definition behaves differently. Need to disable a feature in production that's enabled in staging? Use a feature flag, not environment detection.

## Automated deployment with Workers builds

Manual deployments work for side projects. Production systems need automation: code changes trigger builds, tests run, deployments happen consistently regardless of which engineer pushed the commit.

Workers Builds runs configured build and deployment commands from a connected repository, removing the need to operate a separate CI runner. The team still owns those commands, deployment-token scope and lifecycle, build secrets and promotion policy. Check generated token permissions against the intended deployment boundary; replacing or deleting a token can break subsequent builds.

### Connecting a repository

Workers Builds can connect a repository to build and deploy on changes. Define which branch reaches production, which checks must pass, and which identity may deploy. Keep build and deployment commands in the project's operating documentation.

Pin tooling through the dependency and lockfile policy so local validation and CI use the same version. Worker Previews require Wrangler 4.135.0 or later.

### Preview URLs for every branch

Worker Previews give each branch its own deployed code, configuration, state boundary, and observability under the same Worker. Preview URLs are public by default; use Cloudflare Access when review requires authentication. Stable branch URLs let reviewers follow a change across pushes, while immutable deployment URLs identify the exact version tested. Workers Builds can create these environments as part of pull-request review.

A version-specific URL identifies code; a Preview also separates its configuration and its own Durable Object and Container state. Account-level storage such as KV, D1, and R2 still needs separate resources, and calls to other Workers can reach their production deployments. Chapter 5 covers the resource and trigger limits. Require an explicit review of bindings before treating a Preview as safe for tests that mutate data.

Use Previews for parallel review of individual changes and staging for coordinated integration tests. Neither replaces a gradual production rollout: realistic execution helps find defects, while controlled traffic exposure limits the cost of defects that escape.

### Monorepo support

Organisations with multiple Workers in a single repository need fine-grained control over which Workers rebuild when code changes.

Connect each Worker to the same repository and set its build working directory, such as `services/api/` or `services/auth/`, in Settings → Builds → Root directory. This selects where the build runs; it does not by itself restrict which file changes trigger it.

Build watch paths provide additional control. By default, any file change triggers a build. Configure include and exclude patterns to specify which paths trigger rebuilds:

**Build watch-path settings**

```text
Include paths: services/api/*, shared/utils/*
Exclude paths: *.md, *.test.ts
```

A change to `services/api/handler.ts` triggers the API Worker build. A change to `services/auth/config.ts` doesn't. A change to `shared/utils/helpers.ts` triggers both if both include it in their watch paths. For monorepos with many Workers, this prevents unnecessary builds and keeps deployment times predictable.

Pin the build toolchain as well as application dependencies. Workers Builds updates its default runtimes and package managers independently of your Worker compatibility date. Explicit version settings and lockfiles make a rebuild easier to reproduce; test toolchain upgrades as changes to the build path.

### When to use external CI/CD instead

Workers Builds covers most deployment needs but doesn't fit every situation.

**Self-hosted Git** isn't supported. If your repository lives on self-hosted GitHub Enterprise or GitLab, use external CI/CD with Wrangler commands.

**Complex testing requirements** may need more than Workers Builds provides. If deployment depends on integration tests against staging databases, security scans, or approval workflows, orchestrate those in GitHub Actions or your existing CI platform, then call `wrangler deploy` at the end.

**Multi-service coordination** may need external orchestration to sequence migrations and deployments. A CI runner does not make those calls atomic. Use compatible intermediate states, repeatable steps and an explicit recovery procedure; where a serving change must be indivisible, establish the transaction or routing boundary that supplies that property.

The decision: if your deployment is "build, maybe run tests, deploy Worker," Workers Builds handles it with minimal configuration. Complex orchestration? External CI/CD provides the flexibility you need.

## Private network connectivity

Some backends aren't publicly accessible. Your application needs data from a database inside a VPC, an internal API behind a firewall, a legacy system that cannot be exposed to the internet. Workers VPC connects the Worker to private resources through bindings, without moving its execution into that private network. VPC Services scope a binding to a configured host and port; VPC Networks provide broader reach, with destinations selected at runtime. Choose the access scope before choosing the connection mechanism.

### Cloudflare tunnel: the foundation

Cloudflare Tunnel creates an outbound-only connection from your private network to Cloudflare's edge. Install `cloudflared` on a server inside your network; it establishes a connection to Cloudflare; Workers route requests through that tunnel to your internal resources.

The connector initiates from inside your network, so the backend does not need a publicly reachable inbound listener for this path. Outbound connectivity rules, connector security and service authorisation still matter. Losing the tunnel removes this path to the service; it does not revoke access through other paths.

For production deployments, run at least two `cloudflared` replicas on separate hosts for redundancy. Each host should have minimum 4 GB RAM and 4 CPU cores. The tunnel maintains persistent outbound connections to Cloudflare; ensure the network permits those connections and monitor their health.

### VPC services: the binding layer

> **Beta Feature**
>
> Workers VPC is currently in beta. Features and APIs may change before general availability. While in beta, Workers VPC is available for free to all Workers plans.


VPC Services build on Tunnels to provide a binding-based access model. Rather than giving Workers broad access to everything reachable through a tunnel, you create VPC Services representing specific endpoints, then bind those services to Workers.

**Binding a single VPC service as env.PRIVATE_API**

```jsonc
{
  "vpc_services": [
    {
      "binding": "PRIVATE_API",
      "service_id": "your-vpc-service-id"
    }
  ]
}
```

Replace the service ID with your configured VPC Service ID. The binding selects that configured destination; the URL host and port do not select another internal service:

**Reaching a private endpoint through a VPC binding**

```typescript
const response = await env.PRIVATE_API.fetch(
  "http://internal-api.company.local/users"
);
```

A VPC Service binding restricts the configured destination, reducing the opportunity to pivot to arbitrary internal hosts through that capability. It does not validate attacker-controlled paths or arguments at an allowed service, and other available network paths still need review. Enforce the permitted operation as well as the destination.

VPC Services also enable role-based access control. The Connectivity Directory Admin role creates and manages services; the Connectivity Directory Bind role allows developers to use existing services without the ability to create new ones. This separation matters in larger organisations where infrastructure teams control what's exposed while application teams consume those services.

[Tunnels for Platforms](https://developers.cloudflare.com/tunnel/features/tunnels-for-platforms/) supports fleets beyond the 1,000 tunnels included per account, using the same tunnel mechanism. A tunnel per customer can separate connector credentials and lifecycle for private integrations; the application must still select destinations from authorised tenant configuration. Additional tunnel capacity costs $4.50 per tunnel per month, and inactive tunnels still consume capacity. Automate retirement as well as provisioning.

Tunnel count, route count and VPC Service count are separate limits. Tunnel and Mesh routes have a 50,000-per-account default; buying more tunnels does not increase that limit or the VPC Services allowance. The limit is 1,000 VPC Services per account. Each service represents one endpoint in your private network; you can bind multiple Workers to the same service.

### Cloudflare Mesh and `cf1:network` bindings

For organisations whose private resources are not behind a single tunnel but spread across personal devices, remote servers, and multiple cloud VPCs, Cloudflare Mesh provides a connector-based private network that routes through Cloudflare's edge. A lightweight Cloudflare One Client on each node creates many-to-many private connectivity over private IPs. That path can support configured Gateway policies; connectivity alone does not establish effective inspection. Configure and test the required DNS, posture and DLP controls, including supported traffic, DLP profiles and TLS decryption where needed. Every Cloudflare account gets 50 nodes and 50 users free.

A [VPC Network binding](https://developers.cloudflare.com/workers-vpc/configuration/vpc-networks/) can target a single tunnel or use `cf1:network` for broader account connectivity through Mesh and connected routes, without registering each host as an individual service. That broader reach changes the security decision: an endpoint binding limits destinations by construction, while a network binding requires appropriate network policy and application destination controls. For agents, derive the permitted destination from trusted configuration rather than accepting an arbitrary host supplied by a user or model.

Gateway also offers a different integration: its [Forward action](https://developers.cloudflare.com/cloudflare-one/traffic-controls/integrate-workers/forward-traffic/), in public beta, invokes a Worker on permitted HTTP traffic. Use it to transform requests or responses on an organisation’s controlled outbound path without operating another proxy. This is distinct from a VPC binding that lets application code reach a private backend.

Treat that Worker as part of the enforcement path. Gateway inspects the original request body and the final response, but does not repeat request-side inspection over bytes the Worker changes. Bound transformations and destinations, and test policy ordering, interruptions and failure behaviour. [DLP validation Workers](https://developers.cloudflare.com/cloudflare-one/data-loss-prevention/detection-entries/custom-validation-workers/) serve a narrower purpose: checking a detected pattern against application-specific knowledge. Configure timeout and error fallback deliberately; a failed lookup is not evidence that the original match was false.

### The hybrid edge pattern

Workers become particularly valuable as a global edge layer connecting multiple backend clouds. Your organisation might have databases in AWS, APIs in GCP, and legacy systems on-premises. Workers provide a unified global entry point routing to the appropriate backend based on request type.

A single edge layer means consistent authentication, logging, and rate limiting across all backends. Backend distance, query time and availability still affect each request; consistent ingress policy does not imply consistent latency.

The architectural insight: Workers aren't just a compute platform; they're a global routing layer that happens to execute code. Use that capability to unify fragmented backends into a coherent experience.

## Security practices at the edge

A few security practices deserve explicit mention, not because they're Cloudflare-specific, but because the edge model affects implementation.

### Rate limiting

Distributed rate limiting is hard. Traditional approaches use centralised counters (Redis, typically), but centralised anything adds latency at the edge.

For approximate abuse controls, consider the platform's local rate limiting facilities and the scope in which their counters operate. KV is unsuitable for a precise counter: propagation delay and non-atomic read-modify-write operations can lose increments, with no general 5–10% bound on the error. Chapter 24 distinguishes local limits from strict global quotas.

A Durable Object can own a strict rate limit for one user or quota key. Keep the check and state update atomic; single-threaded JavaScript alone does not prevent interleaving around asynchronous work. Every admission decision adds a call to the object, so measure its latency from the relevant user locations.

Choose based on precision requirements. Approximate limits protect against abuse while being cheap and fast. Exact limits enforce contractual quotas or prevent resource exhaustion where every request over the limit costs real money.

### Input validation

Validate inputs at the edge, before they propagate to backends. Invalid inputs rejected at the edge never consume backend resources.

Use structured validation libraries rather than ad-hoc checks. TypeScript's type system helps at compile time; runtime validation with libraries like Zod catches what types can't express. The combination catches most input errors before they cause problems.

### Dependency minimisation

Workers restrict host access, child processes, and operating-system APIs, reducing the attack surface compared with a traditional server. Maintain that advantage by minimising dependencies.

Every npm package is code you haven't reviewed executing in your security context. Supply chain attacks happen with uncomfortable regularity. Prefer standard APIs over utility libraries. When dependencies are necessary, prefer well-maintained packages with security track records. Audit regularly.

> **Reduced Attack Surface Through Constraints**
>
> Workers do not expose the host filesystem or permit arbitrary child processes. Their virtual filesystem can still contain sensitive bundled or temporary data, and application code can send that data over permitted network calls. Restricted system access reduces the attack surface; careful data handling remains your responsibility.


## What comes next

Security controls define who may act; recovery must preserve those decisions when state is damaged or restored. Chapter 23 follows accepted work through partial failure, reconciliation and the return to safe service.
