Skip to content
Agentmart
Submit a tool

profile-a-worker

Capture a CPU or heap profile of a deployed Cloudflare Worker or Durable Object and read it with pprof.

Skill by joelhooks

IndexedMIT★ 129
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/joelhooks-profile-a-worker-42ebb8

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Capture a CPU or heap profile of a deployed Cloudflare Worker or Durable Object and read it with pprof. Use when a Worker is slow, burns CPU, nears its memory limit, throws Exceeded Memory, or you need to know which function costs the most in production.

Use cases: cloud

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/profile-a-worker

What's inside

Skill name
profile-a-worker
Description
Capture a CPU or heap profile of a deployed Cloudflare Worker or Durable Object and read it with pprof. Use when a Worker is slow, burns CPU, nears its memory limit, throws Exceeded Memory, or you need to know which function costs the most in production.
License
MIT
Instructions
93 lines in SKILL.md · view on GitHub

Before installing

  • Instructions call the network

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Profile a Worker

Cloudflare can sample a deployed Worker or Durable Object while it serves traffic. The result is a pprof file. Each frame is a function. Wider frames cost more CPU time or allocate more memory.

Source: [Profiling in production](https://developers.cloudflare.com/workers/observability/profiling-in-production/).

## Terms used here

- **Isolate:** one running copy of a Worker. A profile samples one isolate that is already loaded.
- **CPU profile:** where CPU time goes. It samples about every millisecond.
- **Heap profile:** where code allocates memory. It records a stack every 512 kB allocated. It does not show retained memory, so it cannot prove a leak by itself.
- **Flat:** cost in the function itself. **Cum:** cost in the function and everything it calls.

## 1. Pick the target

1. Find the deployed script name. Alchemy names it from the app, resource, stage, and a suffix. Read it from the Alchemy state or the dashboard; do not guess it.
2. Pick the version. `latest` is the newest uploaded version, which may not be deployed. After an upload without a deploy, use the deployed version's id.
3. For a Durable Object, use the Worker that owns the namespace, the namespace id, and the 64-character instance id.

## 2. Get read access

Use one of these:

- The `cf` CLI with its own login.
- An API token with **Workers Scripts Read**, taken from your secret store for this one run.

Profiling is read-only. Do not add the token to the repo, `.env.schema`, or CI. Deploy credentials stay in Alchemy profiles.

## 3. Send traffic during the capture

A capture does not invoke your code. It records only what runs during the window.

- Start a load loop against the routes you suspect, then start the capture.
- Keep the loop running for the whole duration.
- `No recent executions` or `no loaded isolate` means the version had no traffic. Send traffic, then retry.

## 4. Capture

API, 10 seconds of CPU:

```sh
curl --fail --silent --show-error --request POST \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/workers/workers/$SCRIPT/versions/latest/profile" \
  --header "Authorization: Bearer $TOKEN" \
  --header "Content-Type: application/json" \
  --data '{"duration_ms": 10000, "profile_type": "cpu"}' \
  --output worker-cpu.pprof
```

- `duration_ms` is 1000 to 50000. `profile_type` is `cpu` (default) or `heap`.
- For a Durable Object, add `namespace_id` and `actor_id` to the body.
- CLI: `cf workers versions profile latest --worker-id "$SCRIPT" --duration-ms 10000 --profile-type cpu > worker-cpu.pprof`.
- The dashboard has the same capture under the Worker's **Observability** tab, view **Flamegraph**.
- Captures are rate limited. On HTTP 429, wait for `Retry-After`.

Check the response before reading it. A failure returns JSON. A success returns protobuf.

```sh
file worker-cpu.pprof
```

The docs say the API returns gzip. In a capture taken on 2026-10-09, it returned raw protobuf (`application/vnd.google.protobuf`). pprof reads both.

## 5. Read it

```sh
go tool pprof -top -nodecount=25 worker-cpu.pprof
go tool pprof -top -lines -nodecount=15 worker-cpu.pprof
go tool pprof -peek 'functionName' worker-cpu.pprof
go tool pprof -http=:0 worker-cpu.pprof
```

- Start with `-top`. Ignore `(idle)` and `(program)`. Note `(garbage collector)`: a high share points to allocation, so take a heap profile next.
- Use `-peek` on a wide frame to see its callers and callees.
- Function names come from the bundle. If the bundler keeps names, they are readable. Locations point at bundle files and lines, such as `file:/bundle/worker.js:3348`, even when source maps upload. Search the bundle or the source for the function name.
- In an Effect program, the fiber runtime (`runLoop`, `makePrimitiveProto`, `succeedWith`) is the floor every request pays. Look below it for your own functions.

## 6. Act on one finding

1. Name the widest function you own and the route that reaches it.
2. Make one change. Common wins: compute a value once instead of per call, [cache a completed value](/lore/cache-completed-values), stop building objects you throw away, remove code that a flag only half disables.
3. Deploy, send the same traffic, capture again for the same duration, and compare the same frame.
4. Record the before and after numbers in the commit message.

One capture samples one isolate for seconds. Take two or three before calling a pattern. Say "this capture shows", not "the Worker always".

## Finish

- The profile file and the command that took it.
- The top frames you own, with flat and cum.
- One change and its measured effect, or the reason no change is worth it.

From joelhooks/rat-stack, MIT.

More from joelhooks/rat-stack

Signals

Stars
129
Forks
8
Open issues
2
Last commit (this folder)
Oct 9, 2026 (19 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

Same skill elsewhere

Copies of this SKILL.md published by others; search shows only one of them.

More from joelhooks

Cite this page

profile-a-worker skill. Agent Mart. https://agentmart.dev/skills/joelhooks-profile-a-worker-42ebb8 (last updated 2026-10-24)