Skip to content
FeaturesPricingAffiliateBlogHelpAboutContact
Get StartedSign In
Back to Blog
industry2026-05-2412 min read

My affiliate marketing PDF returns 500 on asset-proxy — Worker isolate OOM cap gap (PR #616 EEE F5)

Jakub (38) freelance digital marketer Prague Vinohrady (@jakub_foodtech, 27k Czech-Slovak SaaS niche), thMenu affiliate Marketing Assets (PR #551 QQ F4) 14 months (~8 assets/month). Tuesday morning 56-page "Increase Restaurant Revenue 18% with thMenu Pro" high-res brochure InDesign export 247MB upload successful. 8 prospects WhatsApp link. 30min later: **500 Worker Threw Exception**. Engineering Worker Tail logs: `Heap allocation limit exceeded at handleAssetProxy line 42`. Code: `const body = await r2Response.arrayBuffer();` — R2 response full body loaded into Worker memory. 247MB > Cloudflare Workers 128MB isolate limit → instant OOM. Wrong theory: image-proxy already has 25MB cap (PR #521 FF-4) why not asset-proxy? Sibling handler hardening sweep missed. **Asymmetric hardening**: PRs patching one handler miss sibling (recurring pattern PR #585 XX F1, PR #626 GGG F3). **PR #616 batch EEE F5** 3-layer fix: **Layer 1 HEAD-first short-circuit + 25MB cap** `R2.head()` content-length read, head.size > 25MB → 413 Payload Too Large early-return (no memory allocated); ≤25MB → R2.get() + stream-as-you-go `new Response(r2Response.body)` direct streaming, arrayBuffer() avoid. **Layer 2 upload-time cap parity**: upload endpoint reads request Content-Length header + caps 25MB 413 early-return (old code only had indirect Worker isolate protection; multipart stream PUTs support stream-as-you-go so 247MB had landed). **Layer 3 production R2 sweep + cleanup**: grep 25MB+ assets, 6 oversized (50-247MB), proactive email + PDF optimization guide (Adobe Acrobat reduce + Smallpdf + iLovePDF). Jakub 247MB → 18MB optimized (300DPI→150DPI + font subsetting). 24 hours 47 downloads + 12 new restaurant prospects + €420 highest monthly commission of year. Engineering 1-month Pro tier credit + Hall of Fame "Helped harden asset-proxy parity with image-proxy." Burhan Manisa Soma (@burhan_food_growth, 23k Turkish restaurant SaaS niche) version with same flow. Pattern: **Cloudflare Workers / Vercel Edge / AWS Lambda are memory-limited isolate environments. R2/S3/GCS content-fetch must NOT load full body into memory — HEAD-first content-length check + size cap + stream-as-you-go required. Sibling handlers (image-proxy + asset-proxy + reverse-proxy + custom-domain) hardening must be swept; PRs patching one handler can miss sibling.** Implementation checklist: (1) HEAD-first short-circuit R2.head() content-length read oversized 413 early-return; (2) stream-as-you-go new Response(body) direct streaming avoid arrayBuffer; (3) size cap upload time + download time defense-in-depth; (4) upload-time check request Content-Length header read + cap; (5) X-Content-Type-Options: nosniff sweep parity error responses included; (6) production storage sweep oversize asset detect + proactive email optimization guidance; (7) sibling-handler hardening parity audit image-proxy + asset-proxy + reverse-proxy + custom-domain reviewed together; (8) Worker exception monitoring Heap allocation limit exceeded Sentry/Datadog sustained-rate alert.

th

thMenu Team

thmenu.com

Found this helpful? Share it.