DevOps • Performance Engineering
DevOps

CDN Edge Worker Deployment: Build, Test, and Ship Edge Functions

By FlyFish NWA Editorial — Performance Engineering Lead September 8, 2026 9 min read Edge WorkersCI/CD

Edge workers run your code within 50ms of every user on the planet. That power comes with risk: a bad deploy replicates instantly to 300+ PoPs. This guide shows a production-grade pipeline to build, test, and ship CDN edge functions safely — with sub-second rollbacks and zero global downtime.

TL;DR: Bundle with esbuild, test against a local workerd runtime, deploy to a preview environment, canary 5% → 50% → 100% with automated health checks, and keep two previous versions hot for instant alias rollback.

1. Why Edge Deployment Is Different

Unlike origin deployments, edge workers are distributed, stateless, and constrained. You get 1-128 MB memory, 5-50ms CPU limits, and no filesystem. Deploys are not rolling restarts — they are atomic version swaps across the entire Anycast network. A memory leak that would slowly degrade an origin server will instantly degrade every edge node.

Three properties define a safe edge pipeline:

  • Deterministic builds: Identical source must produce identical bundles. Lock dependencies, pin your runtime version, and bundle offline.
  • Environment parity: Your local runtime must match production's V8/workerd isolate. Don't test with Node.js.
  • Progressive delivery: Never go 0 → 100%. Use traffic splitting and automatic rollback on error budget burn.

If you are new to edge performance tradeoffs, start with CDN benefits for performance and security to understand where workers fit versus caching strategies and origin logic.

2. The Deployment Pipeline

A mature edge worker pipeline has five stages. Each stage gates the next, and artifacts flow forward without rebuilds.

Performance Comparison: Edge vs Origin Processing
Metric Edge Processing Origin Processing Improvement
Latency (p50)8–15 ms120–300 ms15–20x faster
Cache Hit Ratio85–95%N/AReduces origin load
TLS Handshake1–5 ms (nearby PoP)50–150 ms10–30x faster
Bandwidth Cost$0.01–0.04/GB$0.05–0.12/GB3–5x cheaper
Availability99.99% (multi-PoP)99.9% (single DC)10x fewer outages

3. Build: Bundle for the Edge

Never deploy raw TypeScript or unbundled node_modules. Edge runtimes execute a single script. Bundling reduces cold starts, enforces size limits, and eliminates dynamic require surprises.

Recommended toolchain

  • esbuild for speed and deterministic output. Set target: es2022 and format: esm.
  • Wrangler / workerd or Fastly Compute toolchain as your deploy CLI. Pin the version in package.json.
  • Size budget: Fail CI if gzipped bundle exceeds 500 KB for Cloudflare Workers or 1 MB for Fastly/CloudFront Functions.
wrangler.toml — production config
name = "edge-router"
main = "dist/worker.js"
compatibility_date = "2026-09-01"
compatibility_flags = ["nodejs_compat"]

[build]
command = "npm run build"

[limits]
cpu_ms = 10

[observability]
enabled = true
head_sampling_rate = 0.1

[placement]
mode = "smart"
src/worker.ts — edge entry with caching
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const cache = caches.default;
    let res = await cache.match(request);
    if (res) return res;

    // Stale-while-revalidate at the edge
    res = await fetch(request, { cf: { cacheTtl: 60, cacheEverything: true } });
    if (res.ok) {
      ctx.waitUntil(cache.put(request, res.clone()));
    }
    return res;
  }
} satisfies ExportedHandler<Env>;

Build in CI with npm ci --ignore-scripts and cache the dist/ artifact. That artifact is what you test and promote — never rebuild between stages. For image-heavy workloads, pair workers with image optimization at the edge to keep CPU under budget.

4. Test: Three Layers of Confidence

Edge workers fail in ways unit tests miss: KV eventual consistency, cache eviction, and subrequest limits. You need three layers.

Layer 1 — Unit tests (fast, isolated)

Mock fetch, caches, and KV. Use Vitest with @cloudflare/vitest-pool-workers so tests run inside workerd, not Node.

Layer 2 — Integration tests against local runtime

Run Miniflare or workerd locally. Test real routing, header mutations, and cache key strategies without network calls. Example assertion: request to /api/* bypasses cache, /static/* hits cache.

Layer 3 — Preview deployment + synthetic traffic

Deploy every pull request to pr-1234.edge-preview.workers.dev with isolated KV namespaces. Run Playwright or k6 against the preview URL. Check performance metrics like Time to First Byte and cache hit ratio before merging.

GitHub Actions — build → test → preview
name: edge-deploy
on: [push]
jobs:
  build-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 20, cache: 'npm' }
      - run: npm ci
      - run: npm run build
      - run: npm test -- --pool=workers
      - name: Deploy preview
        if: github.ref != 'refs/heads/main'
        run: npx wrangler deploy --env preview --branch ${{ github.head_ref }}
      - name: Canary to production
        if: github.ref == 'refs/heads/main'
        run: npx wrangler deploy --env production --strategy canary

Gate merges on bundle size, CPU time (p95 < 10ms in tests), and Lighthouse Core Web Vitals delta. A 100ms regression in LCP should block promotion.

5. Ship: Progressive Delivery and Rollback

Atomic global deploys are dangerous without traffic shaping. Use version aliases and gradual rollouts.

Strategy How It Works Rollback Time Best For
Instant Swap New version replaces old globally at once 30–60s (redeploy) Low-risk config changes
Canary 5/50/100 Route 5% traffic to new version, auto-promote on health <5s (alias switch) All production code changes
Blue/Green Alias Two live versions, switch alias via API <2s Critical paths, checkout flows
Request Header Split Internal users get new version via header Instant (header removal) Dogfooding, QA validation

For e-commerce and high-traffic sites, canary is mandatory. See CDN for e-commerce for patterns on session affinity during canaries. Implementation varies by provider:

  • Cloudflare: Use wrangler versions upload + wrangler versions deploy --percent 5. Keep two previous versions.
  • Fastly Compute: Create new service version, activate with condition randombool(5,100), then promote.
  • AWS CloudFront Functions / Lambda@Edge: Publish new function version and update distribution with traffic weight via CodeDeploy.

Automate health checks: if error rate >0.5% or p95 latency +20% for 2 minutes, automatically shift alias back. Do not require human approval for rollback — require it for promotion.

6. Observability After Ship

You cannot debug what you cannot see. Edge logs are sampled and delayed, so instrument before you need it.

  • Structured logs: Emit JSON with requestId, colo, cpuTime, and cacheStatus. Use console.log with Tail Workers or logpush to R2/S3.
  • Metrics: Track worker_cpu_ms, subrequest_count, kv_read_latency, and error_ratio per version. Alert on version-level anomalies, not global averages.
  • Tracing: Propagate traceparent from edge to origin. Sample 1% in production, 100% in preview.
  • Real User Monitoring: Correlate edge version with Core Web Vitals. A canary that improves TTFB by 40ms but hurts INP will not show in synthetic checks.

Set dashboards to compare canary vs. stable side-by-side. If canary shows higher 5xx or KV timeouts in a single colo, halt promotion — it may be a regional capacity issue, not code.

7. Security and Performance Guardrails

Edge workers have privileged access to every request. Enforce guardrails in CI:

  • Secrets: Never bundle secrets. Use wrangler secret put or environment bindings. Scan bundles for leaked keys with trufflehog.
  • CPU and memory: Fail builds that exceed 80% of limit in load tests. A worker that passes at 5 RPS may OOM at 500 RPS per isolate.
  • Subrequest limits: Cloudflare caps at 50 subrequests; Fastly at similar thresholds. Mock and count them in tests.
  • WAF integration: Run workers after WAF, not before, unless you intentionally handle bot filtering at the edge.

Performance tip: move image resizing and A/B logic to the edge, but keep heavy computation at the origin. Edge CPU is 5-10x more expensive per millisecond than origin CPU.

Done right, edge worker deployment feels like shipping to localhost — fast, safe, and reversible. Build once, test in workerd, canary with metrics, and keep rollbacks instant. Your users will never notice a deploy, which is exactly the point.

Frequently Asked Questions

How long does edge worker deployment take to propagate globally?
Most providers propagate in 10–60 seconds, with full consistency in 2–3 minutes. Use versioned deployments and wait for health checks to pass before shifting 100% of traffic. Avoid instant swaps for code changes — canary for at least 5 minutes.
Should I bundle edge workers or deploy unbundled source?
Always bundle for production with esbuild or Rollup. Bundling cuts cold starts by 30–50%, removes unused code, and locks dependencies. Ship source maps separately for debugging, but never deploy raw TypeScript or node_modules to the edge.
How do I test edge workers that depend on cache and KV storage?
Use the provider's local runtime — Miniflare/workerd for Cloudflare or the Fastly local tester — with mocked KV and cache APIs. For integration coverage, deploy each PR to an isolated preview environment and run synthetic k6 or Playwright traffic against it.
What is the safest rollback strategy for a failing edge worker?
Keep the previous two versions warm and use alias-based rollback. Promote the previous version alias instead of redeploying old code — this reverts globally in under 5 seconds without a new build and preserves your deployment history.

References & Standards: HTTP/2 specification · Cloudflare documentation