13 chapters · 55 min
Skills
Chapter 12 of 13
Reviews and authors Cloudflare Workers code against production best practices.
3 minutes · 679 words · 14 sections
Your knowledge of Cloudflare Workers APIs, types, and configuration may be outdated. Prefer retrieval over pre-training for any Workers code task — writing or reviewing.
Fetch the latest versions before writing or reviewing Workers code. Do not rely on baked-in knowledge for API signatures, config fields, or binding shapes.
| Source | How to retrieve | Use for |
|---|---|---|
| Workers best practices | Fetch https://developers.cloudflare.com/workers/best-practices/workers-best-practices/ | Canonical rules, patterns, anti-patterns |
| Workers types | See references/review.md for retrieval steps | API signatures, handler types, binding types |
| Wrangler config schema | node_modules/wrangler/config-schema.json | Config fields, binding shapes, allowed values |
| Cloudflare docs | Search tool or https://developers.cloudflare.com/workers/ | API reference, compatibility dates/flags |
Before reviewing or writing Workers code, retrieve the current best practices page and relevant type definitions. If the project’s node_modules has an older version, prefer the latest published version.
# Fetch latest workers types
mkdir -p /tmp/workers-types-latest && \
npm pack @cloudflare/workers-types --pack-destination /tmp/workers-types-latest && \
tar -xzf /tmp/workers-types-latest/cloudflare-workers-types-*.tgz -C /tmp/workers-types-latest
# Types at /tmp/workers-types-latest/package/index.d.tsreferences/rules.md — all best practice rules with code examples and anti-patternsreferences/review.md — type validation, config validation, binding access patterns, review process| Rule | Summary |
|---|---|
| Compatibility date | Set compatibility_date to today on new projects; update periodically on existing ones |
| nodejs_compat | Enable the nodejs_compat flag — many libraries depend on Node.js built-ins |
| wrangler types | Run wrangler types to generate Env — never hand-write binding interfaces |
| Secrets | Use wrangler secret put, never hardcode secrets in config or source |
| wrangler.jsonc | Use JSONC config for non-secret settings — newer features are JSON-only |
| Rule | Summary |
|---|---|
| Streaming | Stream large/unknown payloads — never await response.text() on unbounded data |
| waitUntil | Use ctx.waitUntil() for post-response work; do not destructure ctx |
| Rule | Summary |
|---|---|
| Bindings over REST | Use in-process bindings (KV, R2, D1, Queues) — not the Cloudflare REST API |
| Queues & Workflows | Move async/background work off the critical path |
| Service bindings | Use service bindings for Worker-to-Worker calls — not public HTTP |
| Hyperdrive | Always use Hyperdrive for external PostgreSQL/MySQL connections |
| Rule | Summary |
|---|---|
| Logs & Traces | Enable observability in config with head_sampling_rate; use structured JSON logging |
| Rule | Summary |
|---|---|
| No global request state | Never store request-scoped data in module-level variables |
| Floating promises | Every Promise must be awaited, returned, voided, or passed to ctx.waitUntil() |
| Rule | Summary |
|---|---|
| Web Crypto | Use crypto.randomUUID() / crypto.getRandomValues() — never Math.random() for security |
| No passThroughOnException | Use explicit try/catch with structured error responses |
| Anti-pattern | Why it matters |
|---|---|
await response.text() on unbounded data | Memory exhaustion — 128 MB limit |
| Hardcoded secrets in source or config | Credential leak via version control |
Math.random() for tokens/IDs | Predictable, not cryptographically secure |
Bare fetch() without await or waitUntil | Floating promise — dropped result, swallowed error |
| Module-level mutable variables for request state | Cross-request data leaks, stale state, I/O errors |
| Cloudflare REST API from inside a Worker | Unnecessary network hop, auth overhead, added latency |
ctx.passThroughOnException() as error handling | Hides bugs, makes debugging impossible |
Hand-written Env interface | Drifts from actual wrangler config bindings |
| Direct string comparison for secret values | Timing side-channel — use crypto.subtle.timingSafeEqual |
Destructuring ctx (const { waitUntil } = ctx) | Loses this binding — throws “Illegal invocation” at runtime |
any on Env or handler params | Defeats type safety for all binding access |
as unknown as T double-cast | Hides real type incompatibilities — fix the design |
implements on platform base classes (instead of extends) | Legacy — loses this.ctx, this.env. Applies to DurableObject, WorkerEntrypoint, Workflow |
env.X inside platform base class | Should be this.env.X in classes extending DurableObject, WorkerEntrypoint, etc. |
any, no unsafe casts (see references/review.md)npx tsc --noEmit, lint for no-floating-promisesreferences/rules.md for each rule’s correct patternThis skill covers Workers-specific best practices and code review. For related topics:
durable-objects skillwrangler skillInstall this repository
npx skills add cloudflare/skills/plugin marketplace add cloudflare/skillsSkills install per repository, not per chapter — the CLI has no documented per-skill form, so we do not print one.
Reviews and authors Cloudflare Workers code against production best practices. Load when writing new Workers, reviewing Worker code, configuring wrangler.jsonc, or checking for common Workers anti-patterns (streaming, floating promises, global state, secrets, bindings, observability). Biases towards retrieval from Cloudflare docs over pre-trained knowledge.
The verbatim description from this skill’s front matter — the string an agent matches on to decide whether to load it.
main, last pushed 7 August 2026.SKILL.md, not by matching a directory convention. One layout observed: skills/*/SKILL.md..claude-plugin/marketplace.json by Cloudflare, declaring 1 plugin. It is read for editorial metadata only — never as the skill index, which is always the repository tree./cloudflare/skills.md, and each chapter at its own .md URL.2 files · 24 KB
Everything this skill ships beside its prose. All of it is set here, as subchapters of chapter 12.
Documentation the agent loads on demand, rather than up front.