Workers Best Practices
Cloudflare's Workers rules so the agent stops buffering bodies and leaking request state.
I load this when the agent writes or reviews a Worker. Compatibility dates, bindings, and handler contracts drift; the skill tells it to retrieve current Cloudflare docs and flag unbounded body reads, module-level request state, and secrets in source.
Installation
This skill has dependencies (scripts or reference files). Install using the method below to make sure everything is in place.
npx skills add cloudflare/skills --skill workers-best-practicesRequires Node.js 18+. The skills CLI auto-detects your editor and installs to the right directory.
Or install manually from the source repository.
SKILL.md (reference - install via npx or source for all dependencies)
---
name: workers-best-practices
description: Cloudflare Workers best practices for production applications. Use when writing, reviewing, or configuring Workers.
---
# Workers Best Practices
Your knowledge of Cloudflare Workers APIs, types, and configuration may be outdated. **Prefer retrieval over pre-training** when writing or reviewing Workers code.
Use the project's installed versions, generated types, and Wrangler compatibility settings as the baseline for existing code. Retrieve relevant Cloudflare documentation to verify API, configuration, runtime behavior, and limit claims.
## References
Read the sections relevant to the task:
| Reference | When to use it |
|-----------|----------------|
| [Configuration and observability](references/configuration.md) | Compatibility dates, bindings, generated types, secrets, logs, and traces |
| [Runtime patterns](references/runtime-patterns.md) | Streaming, promise lifetime, request state, service calls, security, and runtime tests |
| [Platform API checks](references/platform-apis.md) | Handler signatures, platform classes, binding access, and serialization |
For missing evidence, consult [Workers best practices](https://developers.cloudflare.com/workers/best-practices/workers-best-practices/) or find the affected product in the [Cloudflare docs directory](https://developers.cloudflare.com/directory/). Use the installed Wrangler schema for config fields. A newer type package does not supersede the project's configured target.
## Keep Compatibility Dates Current
Use today's date for new Workers. Encourage periodic updates for existing Workers, reviewing compatibility changes and running relevant tests. Assess existing behavior against its configured date and flags; see [compatibility guidance](references/configuration.md#keep-compatibility_date-current).
## Enable Observability
Enable [Workers Logs](https://developers.cloudflare.com/workers/observability/logs/workers-logs/) and [Traces](https://developers.cloudflare.com/workers/observability/traces/) when creating or preparing a Worker for production. Set `observability.enabled` and `observability.traces.enabled` to `true`; the top-level setting alone does not enable traces. Use structured JSON logging and configure sampling for the workload. During reviews, flag missing logs or traces. See the [configuration example](references/configuration.md#enable-workers-logs-and-traces).
## Anti-Patterns to Flag
| Anti-pattern | Consequence and preferred pattern |
|-------------|-----------------------------------|
| `await response.text()` or similar buffering on unbounded data | Can exhaust Worker memory; [stream large or unbounded bodies](references/runtime-patterns.md#stream-request-and-response-bodies). |
| Hardcoded secrets in source or config | Leaks credentials through version control; use Wrangler secrets. |
| `Math.random()` for security-sensitive tokens or IDs | Predictable values; use `crypto.randomUUID()` or `crypto.getRandomValues()`. |
| Async work started without awaiting, returning, or attaching it to `ctx.waitUntil()` | Work can be dropped and errors missed; tie it to the request or background-work lifetime. |
| Module-level mutable request state | Leaks data across requests and can cause I/O ownership errors; pass request state explicitly. |
| Cloudflare REST API calls for operations available through Worker bindings | Adds network and authentication overhead; use the available binding. |
| `ctx.passThroughOnException()` used as general error handling | Can conceal Worker failures by forwarding to the origin; use explicit error handling and structured error responses. |
| Hand-written `Env` that duplicates Wrangler bindings | Can drift from configuration; generate binding types with `wrangler types`. |
| Direct string comparison of secret values | Can expose timing differences; use the [Web Crypto comparison pattern](references/runtime-patterns.md#use-web-crypto-for-secure-token-generation). |
| Destructuring `ctx` methods, such as `const { waitUntil } = ctx` | Loses the receiver; call `ctx.waitUntil(...)`. |
| `any` on `Env` or handler parameters | Hides binding and handler contract errors; use the project's generated and platform types. |
| `as unknown as T` to force a platform type match | Hides incompatibilities; fix the underlying contract. |
| `implements` used in place of extending a platform base class | Does not inherit runtime behavior, `this.ctx`, or `this.env`; use the appropriate base class. |
| Unbound `env.X` in a platform class method | Bindings are available through `this.env.X`; see [binding access patterns](references/platform-apis.md#binding-access--the-most-common-error). |
| Applying one serialization rule across Queues, Workflow steps, storage, and WebSockets | Can reject valid payloads or accept unsupported ones; check the [specific API and encoding](references/platform-apis.md#serialization-boundaries). |
## Validation
Use the project's existing checks for affected Workers behavior: type-check binding or handler contract changes, and run relevant runtime tests for behavior changes. Preserve required repository checks; a narrow edit does not require a full Workers audit.
## Scope
This skill covers Workers-specific best practices and code review. For related topics:
- **Durable Objects**: load the `durable-objects` skill
- **Workflows**: see [Rules of Workflows](https://developers.cloudflare.com/workflows/build/rules-of-workflows/)
- **Wrangler CLI commands**: load the `wrangler` skill
---
## Companion Files
The following reference files are included for convenience:
### references/platform-apis.md
# Workers Platform API Checks
Use the project's installed and generated types to check affected handlers and bindings. Consult current Cloudflare docs when API or runtime compatibility remains uncertain.
- [Type validation](#type-validation): binding types, handler signatures, and platform classes
- [Serialization boundaries](#serialization-boundaries): encoding and supported values for each API
## Type Validation
### Env interface
- Every binding must have a specific type. Flag `any`, `unknown`, `object`, or `Record<string, unknown>` on bindings.
- Binding types that accept generic parameters (Durable Object namespaces, Queues, Service bindings for RPC) must include them. Read the type definition to confirm which types are generic.
- Use the project's generated binding types; see [configuration guidance](configuration.md#generate-binding-types-with-wrangler-types).
### Handler and class signatures
Verify affected signatures against the project's target type definitions; consult current docs if runtime support or compatibility remains uncertain.
- Correct import path (most Workers platform classes import from `"cloudflare:workers"`)
- Generic type parameter on base classes (e.g., `DurableObject<Env>`)
- `ExecutionContext` as the third param in module export handlers (needed for `ctx.waitUntil()`)
- `fetch()` handlers must return `Promise<Response>`
### Binding access — the most common error
- **Module export handlers** (`fetch`, `scheduled`, `queue`, `email`): bindings via `env.X` parameter
- **Platform base classes** (`WorkerEntrypoint`, `DurableObject`, `Workflow`, `Agent`): bindings via `this.env.X`
Flag `env.X` inside a class extending a platform base class. Flag `this.env.X` inside a module export handler.
### Stale class patterns
Old patterns survive in codebases long after APIs change.
- **`extends` vs `implements`**: platform classes use `extends`, not `implements`. The `implements` pattern is legacy and loses `this.ctx`, `this.env`.
- **Import paths**: verify module specifiers match what types actually export. Common mistake: wrong path for `"cloudflare:workers"` vs `"cloudflare:workflows"`.
- **Renamed properties**: e.g., `this.state` to `this.ctx` in Durable Objects. Search types to confirm.
- **Constructor signatures**: base class constructors change. Verify expected parameters.
## Serialization Boundaries
Check the API and encoding at each boundary. Structured clone support does not imply JSON compatibility or SQL parameter support.
| Boundary | What to check |
|----------|---------------|
| [Queue messages](https://developers.cloudflare.com/queues/configuration/javascript-apis/#queuescontenttype) | Match the body to `contentType`: `json` requires JSON-compatible data, `text` a string, `bytes` an `ArrayBuffer`, and `v8` supports structured-clone values such as `Map` and `Date`. Check the configured compatibility date when relying on the default encoding. |
| [Workflow step results](https://developers.cloudflare.com/workflows/build/workers-api/) | Verify the step result against the documented serialization contract and the project's Workflow types before flagging a value. |
| [Durable Object KV storage](https://developers.cloudflare.com/durable-objects/api/sqlite-storage-api/#put-1) | `storage.put()` supports structured-clone values; do not apply a blanket ban on `Map` or `Set`. |
| [Durable Object SQL](https://developers.cloudflare.com/durable-objects/api/sqlite-storage-api/#exec) | Check bound parameters against the SQL API's supported types. Encode objects explicitly for the intended column representation. |
| [WebSocket messages](https://developers.cloudflare.com/workers/runtime-apis/websockets/#send) | Use `send()` with a string, `ArrayBuffer`, or `ArrayBufferView`; encode objects, for example with `JSON.stringify()`. |
Originally by Cloudflare, adapted here as an Agent Skills compatible SKILL.md.
Works with
Agent Skills format — supported by 20+ editors. Learn more