Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Most large-HTML-to-PDF failures on Heroku are not fixed by adding random Chrome flags. First identify whether Chromium cannot start, the dyno is out of memory, or Heroku’s router timed out waiting for the web request. Then fix that specific cause: use a maintained Chrome buildpack and its launch flags, keep rendering concurrency low, close browser resources, and move long jobs to a worker. If one render still exceeds the dyno’s measured memory, simplify the document or change where it runs.
Identify what actually failed
Start with the complete log entry and the process state, not just the fact that no PDF arrived. A Chrome launch error, a Node memory event, and an H12 router timeout require different fixes. Search the Heroku application logs around the failed job and record the timestamp, dyno type, deployed build, Puppeteer version, and whether the browser process started.
| Signal | What it points to | First check |
|---|---|---|
| Chrome executable or shared-library error | Browser not installed, stale/missing cache, or missing runtime dependency | Check the selected buildpack, PATH, and deployed browser cache. |
| Sandbox or launch failure | Chromium launched without the flags expected in a Heroku dyno | Try the buildpack’s documented --headless and --no-sandbox flags. |
| R14 | Node exceeded its dyno memory quota and is paging to swap | Measure RSS and swap during a single render, then test for concurrency or retained memory. |
| R15 | Memory use vastly exceeded the dyno’s allowance; the process may be killed | Inspect peak memory and reduce per-job demand or move to more capacity. |
| H12 or a client disconnect during PDF generation | The web request may have outlasted the router response window while Chrome was still working | Compare request duration with the router windows and move the render to a worker. |
| Application exception or a growing browser-process count | Unhandled job error or browser/page lifecycle leak | Check cleanup paths and repeat one job at a time while measuring memory. |
Heroku documents an initial 30-second window for a web process to return response data; after the connection is established, each byte sent resets a rolling 55-second inactivity window. A blocked page.pdf() call can therefore trigger a router timeout even if Chromium has not crashed. Do not treat the router error alone as proof of a Chrome failure.
Install a supported Chrome build and use its required flags
Puppeteer’s Heroku troubleshooting guidance recommends adding a Heroku buildpack for Puppeteer and launching with --no-sandbox. The current Heroku Chrome for Testing buildpack installs Chrome and Chromedriver together and makes them available on PATH. Its baseline launch flags are --headless and --no-sandbox. Depending on the specific invocation, --disable-gpu or --remote-debugging-port=9222 may also be needed; do not add them on speculation if the baseline works.
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
- BEST FOR SMALL BUSINESSES – Engineered for extraordinary productivity, the Brother DCP-L2640DW Monochrome (Black & White) 3-in-1 combines laser printer, scanner, copier in one compact footprint and delivers high-quality black & white prints
- FAST PRINTER WITH EFFICIENT SCANNING – Produces documents quickly with print speeds up to 36 ppm(2) and scan speeds up to 23.6/7.9 ipm(3) (black/color). A 50-page auto document feeder(4) allows for convenient, time saving multi-page scanning and copying
- FLEXIBLE CONNECTION OPTIONS – Easily navigate the changing demands of your business with secure multi-device connectivity via built-in dual-band wireless (2.4GHz / 5GHz) and Ethernet. Or connect locally to a single computer via USB interface
- BROTHER MOBILE CONNECT APP – Print, scan, and manage your wireless printer anytime, from almost anywhere from your mobile device. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(5)
- CHOOSE BROTHER GENUINE TONER – When it’s time to replace your toner, be sure to choose Brother Genuine TN830 or TN830XL replacement toner. And with Refresh EZ Print Subscription Service, you’ll never worry about running out of toner again and you’ll enjoy savings of up to 50%(6) on Brother Genuine Toner. Get started with Refresh today with a Free Trial(1)
For a new deployment, do not choose the deprecated heroku/google-chrome buildpack. Heroku directs users to Chrome for Testing, and the newer buildpack does not automatically inject the old shim flags. Follow the selected buildpack’s current installation instructions and verify the Chrome binary is present in the deployed dyno rather than assuming a local development browser will be available there.
Run a minimal deployed smoke test
Before reproducing a huge document, render a small HTML page on the same deployed dyno. This separates browser installation and launch problems from memory pressure caused by the real document.
const puppeteer = require('puppeteer');
const fs = require('node:fs/promises');
(async () => {
const browser = await puppeteer.launch({
executablePath: process.env.CHROME_BIN || 'chrome',
headless: true,
args: ['--headless', '--no-sandbox']
});
try {
const page = await browser.newPage();
await page.setContent('<h1>Heroku PDF smoke test</h1>', {
waitUntil: 'load'
});
const pdf = await page.pdf({ format: 'A4', printBackground: true });
await fs.writeFile('/tmp/smoke-test.pdf', pdf);
await page.close();
console.log('PDF bytes:', pdf.length);
} finally {
await browser.close();
}
})().catch(error => {
console.error(error);
process.exitCode = 1;
});
This test uses Chrome from PATH unless CHROME_BIN is set. If the buildpack specifies a different executable variable or launch setup, use its documented value. A successful smoke test proves only that this small page can be printed; it does not establish that a large production document fits the dyno’s memory.
Check the deployed artifact
Use a Heroku one-off dyno or an equivalent deployed diagnostic to check the binary and versions. The exact Chrome version is controlled by the buildpack release, so check it on the deployment you are debugging.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsRank #2
- BEST FOR HOMES & HOME OFFICES – Engineered for consistent, premium print quality, the Brother HL-L2405W Monochrome (Black & White) Laser Printer delivers sharp, crisp prints at an affordable price. Prints one-sided documents at speeds up to 30ppm(2)
- COMPACT, CONNECTED PRINTER – Flexible connection options make this an ideal printer for home use and at-home offices. Securely connect to multiple devices with built-in dual-band wireless (2.4GHz/5GHz) or locally to a single computer via USB interface
- BROTHER MOBILE CONNECT APP – Manage your printer remotely and print from your mobile device anytime, from almost anywhere. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(3)
- VERSATILE PAPER HANDLING – Enjoy seamless, reliable everyday printing with the 250-sheet paper tray(4) and a manual feed slot that enables printing on envelopes and specialty pape
- BROTHER IS AT YOUR SIDE – Backed by Brother with a 1-year limited warranty and free online, call, or live chat support for the life of your printer
which chrome
chrome --version
node -p "require('puppeteer/package.json').version"
printenv CHROME_BIN
If which chrome returns nothing, the browser buildpack is missing, in the wrong build configuration, or failed to install. If it resolves but Chrome reports a missing shared library, confirm that the chosen buildpack supplies the required system dependencies and that the deployed slug was built after the buildpack change.
Repair Puppeteer’s browser cache when logs point to it
Puppeteer v19 and later changed Chromium’s cache behavior. The Puppeteer Heroku buildpack documents a heroku-postbuild approach that moves /app/.cache/puppeteer into the slug’s local .cache directory. Use one cache strategy consistently; mixing a buildpack-managed Chrome with a separate Puppeteer download/cache assumption can leave the running app looking for a browser that was not deployed.
- Check the package version and the cache path expected by the chosen Puppeteer/buildpack setup.
- Inspect the deployed slug or run a one-off dyno to confirm that the expected browser files exist.
- If errors began after a buildpack or browser change, clear Heroku’s build cache and redeploy so stale artifacts are not reused.
- Repeat the smoke test on the new deployment, then try the large file.
A cache clear is a targeted recovery for stale or missing browser artifacts, not a general remedy for R14, a router timeout, or every Chrome startup failure.
Make PDF rendering safe under memory pressure
Large PDFs can use substantial memory because the HTML layout, page contents, image assets, fonts, browser processes, and generated PDF all have to be handled during the job. There is no universal HTML-byte, page-count, or PDF-size limit that guarantees a render will fit every Heroku dyno. Measure your actual documents and dyno configuration.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #3
- FAST PRINT SPEEDS: Print up to 19 pages per minute.
- COMPACT DESIGN: Space-saving, compact design fits anywhere in your home, school or small office.
- WIRELESS CONNECTIVITY: Print from almost anywhere in your workspace using your compatible mobile device.
- PAPER CAPACITY: Up to 150 sheets.
- SUSTAINABILITY: Uses less than 2 watts in Energy Saver mode.
Start with one job at a time and measure
Record resident set size immediately before a render, at intervals while it runs, and after cleanup. Also record render duration, page count, asset count, and the number of Chrome/browser processes. Run the same document repeatedly at concurrency one. A high peak on the first render suggests per-job demand; memory that remains elevated or climbs after each completed job suggests retained resources or a leak.
function logMemory(label) {
const mb = Math.round(process.memoryUsage().rss / 1024 / 1024);
console.log(`${new Date().toISOString()} ${label} rss_mb=${mb}`);
}
Call logMemory('before') and logMemory('after') around the render, and add periodic measurements while long jobs are running. Node’s RSS does not describe every process in the dyno: inspect dyno-level memory and swap too, because Chrome runs as a separate process.
Close every page and browser on every path
Put cleanup in finally blocks so it runs after successful output and after exceptions. If a worker reuses a browser between jobs, close each page after its job and close the browser during worker shutdown. If repeated measurements show memory retained across jobs, recycle the browser after a bounded number of jobs and verify that this actually controls the trend. Do not run unbounded parallel pages or browser instances; place a queue or semaphore in front of PDF rendering and begin with concurrency one.
Heroku says R14 is emitted when a Node application exceeds its dyno memory quota; paging to swap slows the process. R15 indicates memory vastly exceeded the allowance and the process may be killed with SIGKILL. Heroku’s 2025 dyno-memory documentation gives R15 thresholds of 1 GB for Eco, Basic, and Standard-1X Cedar dynos and 2 GB for Standard-2X Cedar dynos. These figures describe those named Cedar dyno types, not every Heroku generation or plan; check the current memory behavior for the dyno actually running your app.
Rank #4
- BEST FOR HOME OFFICES & SMALL TEAMS – Engineered for consistent, premium print quality, the Brother HL-L2460DW Monochrome (Black & White) Laser Printer produces documents that are clear, crisp, and easy to review and share, all at an affordable price
- COMPACT, CONNECTED, EXCEPTIONALLY EFFICIENT– Connect with built-in dual-band wireless (2.4GHz/5GHz), Ethernet, or to a single computer via USB interface. Prints at speeds up to 36ppm(2), plus automatic duplex printing saves time and reduces paper waste
- BROTHER MOBILE CONNECT APP – Manage your wireless printer remotely and print from your mobile device anytime, from almost anywhere. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(3)
- VERSATILE PAPER HANDLING – Tackle high-volume black & white printing with the 250-sheet capacity paper tray.(4) The manual feed slot enables printing on envelopes and specialty paper
- BROTHER IS AT YOUR SIDE – Backed by Brother with a 1-year limited warranty and free online, call, or live chat support for the life of your printer
Move long renders out of the web request
If the render can exceed Heroku’s router window, use an asynchronous job flow rather than holding a browser connection open while a synchronous request waits for page.pdf(). A practical architecture is:
- The web process validates the request and stores a job record or queue message.
- It returns a job ID promptly, before rendering begins.
- A worker with bounded concurrency loads the document, creates the PDF, and stores the result in durable storage.
- The client polls a job-status endpoint or receives a notification, then downloads the finished file through an authorized route or signed storage link.
- The worker records a clear failure state and cleans up its page/browser even when navigation or printing fails.
Keep the job status separate from the PDF response: a web request should not have to stream artificial progress simply to keep the router connection alive. If a synchronous PDF response is unavoidable, set Puppeteer navigation and operation timeouts deliberately, and ensure the application design can return data within the router’s allowed windows. A timeout setting does not make a slow render finish faster; it makes failure boundaries explicit.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If the page you need to capture is reachable by URL and an image capture is enough, ScreenshotNeo is a website screenshot API with a one-request flow. The API also supports PDF output, but the example below is the supplied image-capture call; use the ScreenshotNeo API documentation for the PDF request details rather than treating this image example as a PDF response.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
ScreenshotNeo accepts cookie/consent banners like a visitor before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteCreate a free ScreenshotNeo account for 1,000 screenshots a month with no card.
Best Value
- FROM AMERICA'S MOST TRUSTED PRINTER BRAND – Perfect for small teams printing professional-quality black & white documents and reports. Perfect for 1-3 people
- WORLD'S SMALLEST LASER IN ITS CLASS – Precision laser printing that fits anywhere
- FAST PRINT SPEEDS – Up to 21 black-and-white pages per minute single-sided
- WIRELESS WITH SELF-RESET – Helps you stay connected
- PRINT FROM ANY DEVICE – Wireless printing from any mobile device, PC or tablet. Works with Microsoft, Mac, AirPrint, Android, Chromebook and more
Choose where the workload should run
| Approach | Best fit | Trade-off |
|---|---|---|
| Chrome in a Heroku worker | Measured jobs fit the available memory and can run asynchronously. | You maintain Chromium, fonts, cache behavior, upgrades, and crash recovery. |
| Larger Heroku dyno | The application is otherwise healthy and measured peak memory is the limiting factor. | It raises runtime cost and does not fix leaks, excessive concurrency, or a synchronous router design. |
| Managed browser/PDF service | You need isolation, burst capacity, or less browser operations work. | It adds an external dependency, vendor terms and cost, and possible data-transfer or privacy considerations. |
Make this decision using peak memory for one job, expected queue depth, render latency, failure rate, and the operational work you can support. First correct leaks and unbounded concurrency. Only then decide whether a larger dyno or an external service is the right capacity trade-off.
Troubleshooting by symptom
Chrome fails before opening a page
- Confirm the Chrome for Testing or Puppeteer Heroku buildpack is installed and the executable is on
PATH. - Use the flags documented for that buildpack; for the current Chrome for Testing setup, start with
--headlessand--no-sandbox. - For missing-library messages, verify the runtime dependencies and browser artifact in the deployed slug; clear the build cache only if stale/missing artifacts are implicated.
It works locally but not on Heroku
- Compare the deployed Chrome and Puppeteer versions with local versions rather than assuming they match.
- Check whether the deployed cache actually contains the browser Puppeteer expects, particularly with Puppeteer v19 or later.
- If output uses Chinese, Japanese, or Korean characters incorrectly or with missing glyphs, install the required extra font files as noted in Puppeteer’s Heroku guidance.
The job emits R14/R15 or the dyno restarts
- Render once at concurrency one and inspect dyno memory, RSS, and swap.
- Close pages and browsers on both success and failure; repeat jobs to reveal retained growth.
- If one-job peak remains above the quota, reduce document/asset complexity or select more memory. Do not expect a larger dyno to cure a leak.
The request times out but there is no Chrome error
- Check whether
page.pdf()is blocking the web handler while the router waits for response data. - Move the work to a queue-backed worker and return a job ID promptly.
- If a synchronous path must remain, choose explicit navigation and operation timeouts and design response behavior around Heroku’s documented router windows.
Operational checklist before redeploying
- Classify the log signature before changing flags or dyno size.
- Verify the selected maintained buildpack, Chrome executable, versions, and deployed browser cache.
- Pass a small deployed smoke test with
--headlessand--no-sandbox. - Test the largest representative document alone and collect memory, swap, duration, page, asset, and process counts.
- Enforce bounded render concurrency and guaranteed page/browser cleanup.
- Use a worker architecture for jobs that can outlast the router window.
- After each change, rerun the same workload and compare logs and measurements; do not infer a fix from a successful small-page test.
Frequently Asked Questions
Is there a universal maximum HTML file size or page count for Heroku PDF generation?
No universal maximum is established in Heroku’s or Puppeteer’s guidance cited here. The usable limit depends on document content, assets, Chrome memory use, concurrency, and the dyno’s available memory, so measure representative jobs on the target dyno.
Do I have to use a Heroku worker if PDF generation is slow?
Not for every render, but a job that may outlast the router windows should be moved to an asynchronous worker flow. A worker changes how the request is handled; it does not increase the memory available to an individual render.
Recommended Free Tools
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

