Skip to content

worker: respect Browser Run's launch cadence and daily budget - #55

Merged
Aswinmcw merged 3 commits into
mainfrom
fix/browser-session-reuse
Sep 16, 2026
Merged

Aswinmcw merged 3 commits into
mainfrom
fix/browser-session-reuse

Conversation

@Aswinmcw

@Aswinmcw Aswinmcw commented Sep 16, 2026 •

Copy link
Copy Markdown
Member

Problem

After #54 and the twenty theme PRs, rendering two uncached theme PDFs back to back on production fails: the first renders in 5–10 s, the second returns 502 Failed to render PDF. in ~0.5 s.

This account is on Workers Free, where Browser Run allows one new browser every 20 seconds, 3 concurrent, and 10 minutes of browser time per UTC day. With one theme nobody rendered twice in 20 s; with twenty-one a visitor clicking through /themes does it immediately.

Fix

  • launchBrowser() consults puppeteer.limits() and, when no launch is allowed yet, waits for the next slot (up to 25 s) instead of failing.
  • One fresh browser per render, closed in finally. (An earlier revision of this PR kept sessions alive for reuse; that burns the 10-minute daily budget while idle — two kept-alive sessions used the whole day's allowance during testing — so it was reverted.)
  • A launch refused while the budget says yes is the daily cap: reported as 503 with Retry-After: 3600 and a readable message, instead of a bare 502. Limits are logged next to every render failure.

Test plan

  • tsc --noEmit
  • Preview: pages and cached PDFs serve normally; an uncached PDF with the daily budget exhausted returns the 503 with Retry-After (verified today, since testing spent the budget).
  • After the UTC reset: two uncached PDFs back to back both return 200, the second after a ≤ 25 s wait. Cannot be verified until then.

🤖 Generated with Claude Code

With one theme a visitor rarely rendered two PDFs in quick succession;
with twenty-one they do, and Browser Run refuses a second new browser
within about a minute of the first, so the second uncached PDF returned
502 in half a second.

Keep the browser alive for ten minutes after a render (disconnect instead
of close), reattach to an idle session on the next render, and only launch
when none is free, retrying twice with a short backoff when the launch is
refused. Log the account's Browser Run limits alongside a render failure
so the cause is visible without reproducing it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Aswinmcw
Aswinmcw requested review from a team and Aswin-coder as code owners September 16, 2026 08:50

@Aswincloud-Bot Aswincloud-Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-approved: @Aswinmcw is a member of @Aswincloud/admins.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
resume da4d508 Commit Preview URL

Branch Preview URL
Sep 16 2026, 09:08 AM

Aswin and others added 2 commits September 16, 2026 14:22
A session released by a render that just finished is not listed as idle
for a moment, so a request that arrived meanwhile burned its launch retries
and failed even though a browser was about to be free. Loop for up to 15s:
reattach if a session is idle, launch only while the account's per-minute
launch budget allows, otherwise wait and look again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…daily budget is spent

Keeping browsers alive was the wrong trade on Workers Free: an idle
session consumes the 10-minute daily browser-time budget as fast as a
working one, and two kept-alive sessions burned the whole day's allowance.
Revert to one fresh browser per render, closed in finally.

The failure a visitor actually hits is the launch cadence (one new browser
every 20 s): the second uncached PDF used to fail in half a second. Now
launchBrowser consults puppeteer.limits() and waits up to 25 s for the next
slot. A refusal while the launch budget says yes is the daily cap, which is
reported as 503 with Retry-After and a human-readable message instead of a
bare 502.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Aswinmcw Aswinmcw changed the title worker: reuse Browser Run sessions between PDF renders worker: respect Browser Run's launch cadence and daily budget Sep 16, 2026
@Aswinmcw
Aswinmcw added this pull request to the merge queue Sep 16, 2026
Merged via the queue into main with commit 1333544 Sep 16, 2026
2 checks passed
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.

2 participants