Skip to content

fix(worker): cut CPU per request below the free plan limit - #100

Merged
ajithakdev merged 1 commit into
mainfrom
fix/worker-cpu
Oct 30, 2026
Merged

ajithakdev merged 1 commit into
mainfrom
fix/worker-cpu

Conversation

@ajithakdev

Copy link
Copy Markdown
Owner

The worker was using more CPU per request than the Cloudflare free plan allows (10 ms). Over the last 30 days, the 99th percentile reached 28 to 77 ms. Nothing has failed yet at today's traffic, but under load Cloudflare can cut those requests off mid-test.

Two causes, both fixed:

  • Downloads streamed 64 KB chunks, so a 25 MB file meant 400 trips through JavaScript. They now stream 4 MiB chunks (7 trips). The last chunk is trimmed, so 1, 5, 10 and 25 MB all come out exact; a new test checks every allowed size.
  • Uploads were read chunk by chunk in JavaScript just to count bytes. A body with a declared Content-Length is now refused up front if it's over the 16 MB cap, and otherwise read in one native arrayBuffer() call. Bodies without a length (chunked) still go through the old counting loop. The extension always sends a length, and never more than 8 MB.

Measured on Cloudflare with wrangler versions upload preview versions (production untouched), using the same 25 MB downloads and 5 MB uploads:

Version CPU p50 CPU p90 CPU p99
Production (d6779235) 16.1 ms 20.4 ms 20.4 ms
1 MiB chunks 6.6 ms 13.0 ms 13.0 ms
4 MiB chunks, old upload read 4.0 ms 26.6 ms 34.2 ms
4 MiB chunks + native upload read (afe4630d) 5.6 ms 7.2 ms 12.6 ms

Also: CI now lints and type-checks the worker, @meterx/shared and @meterx/reports (#86 asked for this). All three pass with no new findings.

Deploys with the next release (cd services/worker && npx wrangler deploy). Nothing in the API changes, so the extension needs no update.

@ajithakdev

Copy link
Copy Markdown
Owner Author

Pre-merge checklist

Addressed

  • Downloads stream in 4 MiB chunks; the last chunk is trimmed so every size comes out exact
  • Uploads with a declared Content-Length over 16 MB get 413 up front; others are read with one arrayBuffer() call
  • Chunked uploads (no length) still go through the counting loop and still hit the 16 MB cap
  • Missing, zero, NaN or negative Content-Length falls through to the loop safely

Tested

  • npm test: 111 tests pass (reports 16, shared 15, extension 46, site 9, server 13, worker 12), plus the scripts docs check
  • Both new worker tests pass (declared length 200/413, every allowed size exact)
  • npm run lint (0 errors) and npm run build pass; tsc --noEmit clean in worker, shared and reports
  • wrangler dev: 1, 5, 10 and 25 MB downloads exact (1 MB all zeros); 1 MB and 8 MB uploads 200; 17 MB upload 413 (with length and chunked); text/plain 415; /ping, /health, /ip 200; CORS and Timing-Allow-Origin headers present
  • Preview version c146df3a (uploaded with wrangler versions upload, production untouched): same checks pass, plus 10 rounds of 25 MB download and 5 MB upload
  • CPU on that preview (34 requests, 0 errors): p50 4.5 ms, p90 8.0 ms, p99 10.0 ms
  • Full speed test from the extension pointed at the preview URL (not run; API is unchanged)
  • CPU under real traffic after deploy

CI and release

  • CI check green, now with the extra type-check step
  • No API change, so no extension update needed

Docs

  • CHANGELOG Unreleased has both lines

After merge
Deploys with the Sunday release: cd services/worker && npx wrangler deploy. Then check CPU p99 for the new version in Workers analytics after a day of traffic.

@ajithakdev

Copy link
Copy Markdown
Owner Author

Accuracy check (A/B against main)

Two preview versions (main 70c954fa vs this PR c146df3a), the real runTest() from the extension run in Node, interleaved in both orders, 13 runs each:

Metric main this PR
Download (median) 96.4 Mbps 96.0 Mbps
Upload (median) 17.5 Mbps 17.5 Mbps
Idle ping 490 ms 480 ms
Loaded ping during download 514 ms 570 ms
Bufferbloat grades A4 B3 C3 D3 A2 B1 C2 D7 F1
  • Download and upload speeds unchanged
  • Ramp-up difference is inside the 1.2 s trim
  • Loaded ping during download looks about 55 ms higher (B worse in 10 of 13 pairs, both orders). Weak signal on a 480 ms link; may simply mean the worker now keeps the link fuller

@ajithakdev
ajithakdev merged commit 6cd7e5c into main Oct 30, 2026
2 checks passed
@ajithakdev
ajithakdev deleted the fix/worker-cpu branch October 30, 2026 20:32
@ajithakdev ajithakdev self-assigned this Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant