zudo-cloudflare-wisdom
GitHub repository

Type to search...

to open search from anywhere

Standalone Workers

Deploying independent Workers separate from Pages

When to Use

Standalone Workers are best for:

  • Search workers -- Dedicated search APIs with their own data and dependencies

  • AI chat workers -- LLM-powered endpoints with API key bindings

  • Webhook handlers -- Receiving callbacks from external services

  • Proxy workers -- Routing or transforming requests

Project Structure

A typical standalone Worker project:

packages/my-worker/
├── src/
│   └── index.ts
├── wrangler.toml
├── package.json
└── tsconfig.json

Worker Entry Point

// src/index.ts
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);

    if (url.pathname === "/api/search") {
      return handleSearch(request, env);
    }

    return new Response("Not Found", { status: 404 });
  },
};

ExecutionContext and Background Processing

The third argument to fetch is ExecutionContext, which provides waitUntil() for running async work after the response is sent:

export default {
  async fetch(
    request: Request,
    env: Env,
    ctx: ExecutionContext,
  ): Promise<Response> {
    // Return response immediately
    const response = buildResponse(request, env);

    // Run non-critical work in the background
    ctx.waitUntil(logAnalytics(request, env));
    ctx.waitUntil(updateCache(request, env));

    return response;
  },
};

This is critical for:

  • Webhook handlers -- Slack, GitHub, etc. require responses within 3 seconds. Process the webhook payload after responding.

  • Logging and analytics -- Don't block the user's response for non-critical writes.

  • Cache warming -- Update caches after serving a response.

:::warning[waitUntil does not extend CPU time] ctx.waitUntil() keeps the Worker alive after the response is sent, but does not increase the CPU time limit. Long-running operations may still be terminated. :::


## Deployment

Deploy with `wrangler deploy` (not `wrangler pages deploy`):

```bash

npx wrangler@4 deploy

In CI, deploy from the worker's directory:


- name: Deploy Worker
  working-directory: packages/my-worker
  run: pnpm run deploy
  env:
    CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
    CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

Path-Triggered Deploys

For monorepos with multiple workers, trigger deploys only when the worker's files change:


on:
  push:
    branches:
      - main
    paths:
      - 'packages/my-worker/**'
  workflow_dispatch:  # Allow manual triggers

This avoids unnecessary deploys when other parts of the monorepo change.

Revision History

Takeshi TakatsudoCreated: 2026-04-04T22:50:44+09:00Updated: 2026-06-20T12:51:21+09:00