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.

Terms used here

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:

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.

4. Capture

API, 10 seconds of CPU:

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

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

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

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

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 value7, 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


Last changed 2026-10-09 in 1bc586c. Source on GitHub. Change log.