Cloudflare Operations

SkillCloud & infra

Cloudflare Workers + Wrangler edge ops: runtime, bindings, local dev, secrets, deploy/CI, Pages-vs-Workers. Triggers on: cloudflare workers, wrangler, wrangler deploy, wrangler.toml, KV, D1, R2, durable objects, queues, vectorize, compatibility_date, edge functions, illegal invocation, waitUntil, caches API, smart placement, email service, vitest-pool-workers, wrangler dev host.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Cloudflare Operations skill

What this skill tells your AI

The instructions your AI receives, as published by 0xdarkmatter/claude-mods in skills/cloudflare-ops/SKILL.md and read by ahel’s review.

Cloudflare Workers + Wrangler: runtime patterns, bindings, local dev, secrets, deploy, CI/CD, observability.

Ecosystem facts verified as of 2026-07.

Version context (verified 2026-07): Wrangler v4.x · config is wrangler.jsonc (Cloudflare's recommended format for new projects — some newer features are JSON-config-only; wrangler.toml still works and is widespread in older repos) · deploy command is wrangler deploy (the old wrangler publish is deprecated — see gotchas). Workers can now serve static assets, which is the current direction for full-stack and static sites over Pages (see Workers vs Pages).

Reference Files

FileCovers
references/bindings.mdEvery binding (KV/D1/R2/DO/Queues/Hyperdrive/AI/Vectorize/Service/Analytics Engine) — config block, runtime API, when to reach for each, consistency model
references/workers-runtime.mdRuntime APIs, handlers (fetch/scheduled/queue/email/tail), CORS, caching, streaming, WebSockets, Durable Objects deep-dive, limits
references/workers-runtime-gotchas.mdProduction footguns: detached fetch ("Illegal invocation"), per-colo caches vs KV vs D1, waitUntil semantics + outbox pattern, testing cron handlers, test-workerd lagging production, Email Service account states, Smart Placement, wrangler dev host rewriting
references/deploy-and-cicd.mdwrangler deploy, environments, secrets, Workers Builds, GitHub Actions + OIDC/API-token, gradual deployments, rollbacks, observability
assets/wrangler.jsonc.templateCommented, current wrangler.jsonc covering all common bindings + assets

Access / Zero Trust auth patterns (verifying Cf-Access-Jwt-Assertion, AUD tags, service auth, closed origins) → auth-ops skill, references/cloudflare-access.md.

Workers vs Pages Decision

Cloudflare added static-asset hosting to Workers; a single Worker now serves a static site, a full-stack app, or an API + SPA. For new projects, default to Workers with static assets. Pages still works and isn't deprecated, but Workers has the broader, faster-moving feature set (Durable Objects, Cron Triggers, Queues, richer observability) and is where Cloudflare's investment goes.

New project?
│
├─ Pure static site (no server logic)
│  └─ Workers + assets binding (asset-only — requests matching files never invoke Worker code, $0 for those).
│     Pages is also fine here; Workers keeps one platform if you later add logic.
│
├─ Full-stack / SPA + API / SSR framework (Next, Astro, Remix, SvelteKit, Hono)
│  └─ Workers + assets + a Worker script. Use the framework's Cloudflare adapter (C3: `npm create cloudflare@latest`).
│     This is the current recommended path — Pages' framework story is converging into Workers.
│
├─ Already on Pages and happy
│  └─ Stay. "What works in Pages works in Workers" — migrate only when you need a Workers-only
│     feature (DO, Cron, Queues, advanced observability). See the migrate-from-pages guide.
│
└─ Need Durable Objects / Cron Triggers / Queues / Tail Workers
   └─ Workers (these are Workers-only).

Asset serving modes (in the assets block): asset-only (no main) serves files directly and never bills Worker invocations for matches; assets + Worker serves matching files first, falls through to your fetch handler for everything else (or set run_worker_first to invoke the Worker before asset matching). Reach assets from code via env.ASSETS.fetch(request).

Wrangler Config Skeleton (jsonc)

Full annotated version: assets/wrangler.jsonc.template.

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-worker",
  "main": "src/index.ts",
  "compatibility_date": "2026-06-01",   // pins the runtime version — REQUIRED, bump deliberately
  "compatibility_flags": ["nodejs_compat"],  // opt-in runtime features (Node built-ins, etc.)

  "observability": { "enabled": true },  // turn on Workers Logs (off by default)

  "assets": { "directory": "./public", "binding": "ASSETS" },

  "kv_namespaces": [{ "binding": "CACHE", "id": "<kv-id>" }],
  "d1_databases": [{ "binding": "DB", "database_name": "app", "database_id": "<d1-id>" }],
  "r2_buckets":   [{ "binding": "BUCKET", "bucket_name": "uploads" }],

  "vars": { "ENVIRONMENT": "production" },  // NON-secret config only — never put secrets here

  "env": {
    "staging": { "vars": { "ENVIRONMENT": "staging" } }  // named env: deploy with --env staging
  }
}
  • compatibility_date = yyyy-mm-dd, selects the runtime version. It's required and load-bearing: bumping it can change behaviour, so do it deliberately and test. compatibility_flags opt into upcoming/Node-compat features (e.g. nodejs_compat).
  • Keep secrets OUT of vars — they land in plaintext in the deployed config. Use wrangler secret put / .dev.vars (secrets).
  • TOML equivalent still parses; the binding shapes map 1:1 ([[kv_namespaces]], [[d1_databases]], …). New repos: prefer jsonc.

Bindings Table — When Each

Full config + runtime API for every binding: references/bindings.md.

BindingReach for it when…Consistency / note
KVRead-heavy config/cache, infrequent writes, global readsEventually consistent (~60s propagation). Fast reads, slow-ish writes. Not for "read your own write".
D1Relational/SQL data, moderate scale, per-app databaseSQLite at the edge. Strong within a DB; read replication is async. Use for app data with joins.
R2Object/blob storage, large files, zero egress feesS3-compatible. Replaces S3 for media/backups/assets you serve.
Durable ObjectsStrong consistency, coordination, stateful realtime (chat, presence, game rooms, rate limit counters)Single-threaded per object instance = serialized = consistent. The answer when KV's eventual consistency bites. SQLite-backed storage available.
QueuesAsync/background work, decoupling, batching, retriesProducer binding + consumer Worker. Smooths spikes; guaranteed delivery with retries + DLQ.
HyperdriveConnecting to an existing external Postgres/MySQL with pooling + edge cachingMakes a regional DB feel fast from Workers. Needs nodejs_compat.
Workers AIRun inference (LLM, embeddings, image) on Cloudflare's GPUsai binding → env.AI.run(model, ...). Pairs with Vectorize for RAG.
VectorizeVector DB for embeddings / semantic search / RAGvectorize binding. Store + query embeddings, often fed by Workers AI.
Service bindingsWorker-to-Worker RPC without a network hopZero-latency internal calls; compose Workers as services.

Decision shortcut: need strong consistency or coordination → Durable Objects. Relational queries → D1. Big files → R2. Cheap global cache → KV. Background work → Queues. External SQL DB → Hyperdrive.

Minimal Worker

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    if (url.pathname === "/health") return Response.json({ ok: true });
    return new Response("Hello from the edge");
  },
};

env carries every binding (env.DB, env.CACHE, env.ASSETS, secrets, vars). ctx.waitUntil(promise) runs background work after the response is sent. Workers require ES module format (export default { fetch }) — the old service-worker addEventListener("fetch") format is legacy. Full handler patterns (scheduled/queue/email/tail, CORS, caching, WebSockets, DO): references/workers-runtime.md.

Local Dev & Secrets

npm create cloudflare@latest my-app   # C3 scaffolder — picks framework + adapter + wrangler.jsonc
wrangler dev                          # local dev server (Miniflare/workerd) on localhost:8787
wrangler dev --remote                 # run on Cloudflare's edge (real bindings) instead of local sim
wrangler types                        # generate TS types for env from your bindings → worker-configuration.d.ts

Secrets (never in vars):

WhereMechanism
Local dev.dev.vars file (dotenv format, gitignored) — wrangler dev loads it as env.*. Per-env: .dev.vars.staging.
Deployedwrangler secret put NAME (prompts for value, encrypts it) · wrangler secret list · wrangler secret delete NAME
CI bulkwrangler secret bulk secrets.json
NewerCloudflare Secrets Store bindings (account-level shared secrets) — see deploy reference

Add .dev.vars* to .gitignore. vars in config = plaintext public config; secrets are encrypted and write-only.

Deploy & CI/CD

Full detail: references/deploy-and-cicd.md.

wrangler deploy                  # build + upload + activate (NOT `wrangler publish` — deprecated)
wrangler deploy --env staging    # deploy a named environment
wrangler versions upload         # upload a new version WITHOUT making it live (gradual deploys)
wrangler versions deploy         # split traffic across versions (e.g. 10% new / 90% old)
wrangler rollback                # revert to the previous deployed version
wrangler tail                    # stream live logs from the deployed Worker
  • Workers Builds — Cloudflare's native git-connected CI: push to GitHub/GitLab, Cloudflare builds + deploys. Zero-config for simple Workers; the default for most teams.
  • GitHub Actionscloudflare/wrangler-action. Authenticate with a scoped API token (CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID as secrets), least-privilege (Workers Scripts:Edit). Template + workflow in the deploy reference.
  • Gradual deploymentsversions upload then versions deploy to shift a percentage of traffic; instant rollback if metrics regress.

Observability

  • "observability": { "enabled": true } in config turns on Workers Logs (structured console.log capture in the dashboard) — off by default, opt in.
  • wrangler tail for live request log streaming during an incident.
  • Tail Workers — a Worker that receives execution traces of another Worker (centralised logging/alerting).
  • Analytics Engine — write custom time-series metrics from a Worker (env.AE.writeDataPoint(...)), query via GraphQL/SQL API.

Common Gotchas

Runtime-level footguns that pass tests and ship — detached fetch ("Illegal invocation"), per-colo caches, waitUntil guarantees, cron testing, the test workerd lagging production, Email Service account states, Smart Placement, wrangler dev rewriting the request host — each with symptom/why/fix: references/workers-runtime-gotchas.md.

GotchaDetailFix
wrangler publish is goneRenamed to wrangler deploy (Wrangler v3+). Old tutorials/CI still say publish.Use wrangler deploy. Update any publish in scripts/CI.
wrangler.toml vs .jsoncBoth parse, but newer features are JSON-config-only and Cloudflare recommends jsonc for new projects.New projects: wrangler.jsonc. Migrating: wrangler.toml → jsonc is a mechanical 1:1.
Missing compatibility_dateRequired; absent or stale date silently pins old runtime behaviour.Set it; bump deliberately and test — it can change semantics.
CPU time limitDefault 30s CPU per invocation (was 10ms/50ms historically; raised). Wall-clock can be longer while awaiting I/O. CPU-bound loops still get killed.Offload heavy compute; use Queues for long async work; check the limits page for your plan.
Script size limit3 MB (free) / 10 MB (paid) gzipped.Trim deps, dynamic-import large modules, avoid bundling node-only libs.
KV eventual consistencyA write isn't globally visible for up to ~60s; not "read your own write".Use Durable Objects when you need strong consistency.
Node built-ins failfs, crypto, etc. aren't there by default."compatibility_flags": ["nodejs_compat"] enables a polyfill subset; check what's actually supported.
Secrets in varsvars ships plaintext in the deployed config.wrangler secret put (deployed) / .dev.vars (local).
request/response body read twiceStreams are single-use.request.clone() before the first read.
Bundling surprisesWrangler uses esbuild; some packages assume Node/CommonJS.Prefer Workers-compatible libs; set nodejs_compat; check the build output.

Setup

  1. Install: npm install -g wrangler (or use npx wrangler / npm create cloudflare@latest to scaffold).
  2. Auth: wrangler login (OAuth) for local; API token for CI.
  3. Copy assets/wrangler.jsonc.template, strip the bindings you don't need, fill in IDs.
  4. wrangler devwrangler deploy.

Staleness verifier

This skill encodes fast-moving facts (Wrangler major line, recommended compatibility_date, wrangler.jsonc config convention). scripts/check-cloudflare-facts.py guards them against silent drift:

# Structural (PR CI, no network): every catalogued fact's prose_token is still
# named in this skill's prose (incl. the jsonc template), and the currency
# note still carries a year.
python scripts/check-cloudflare-facts.py --offline        # exit 0 consistent, 10 drift

# Live (freshness job, never blocks a PR): wrangler still resolves on npm and
# its latest major matches the documented v4.x line.
python scripts/check-cloudflare-facts.py --live            # exit 10 major drift, 7 npm unreachable

The canonical fact set lives in assets/cloudflare-facts.json; when the Wrangler major, the recommended compatibility_date, or the config convention changes, update it to match or --offline fails CI.

Signals

GitHub stars
36
Forks
5
Last commit
Aug 2026

ahel review

  • S4info
    community integration — published by 0xdarkmatter, not cloudflare

Automated review, not a security audit. Ruleset v1.

Advanced
Catalog kind
skill
Gateway key
cloudflare-ops
Source
github.com/0xdarkmatter/claude-mods