Reference

Why your PDF renderer will not deploy

The generic advice is that a browser is large and that this causes problems. That is true and it does not help anyone at four in the afternoon with a failing deploy. What helps is the specific limit: 250 megabytes unzipped, 64 megabytes of shared memory, a 500 megabyte slug, a plan with no package manager. Each page below has one of those, the error text it produces, the fix, and what the fix still costs afterwards.

Renderers covered: Puppeteer, Playwright, wkhtmltopdf, WeasyPrint. Once the deployment works, the next set of problems is in the output rather than the infrastructure: what goes wrong when HTML becomes a PDF.

Serverless functions

AWS Lambda

a function that is handed a request, runs, and is frozen again. The execution environment is reused between invocations but you do not control when it is torn down.

Vercel

serverless functions built from your repository, plus an edge runtime that is a different environment entirely.

  • Puppeteer: a bundler that cannot see the browser
  • Playwright: an install step the build never runs

Netlify Functions

AWS Lambda underneath, with Netlify's own bundling step in front of it.

Azure Functions

a function host that runs your code inside an environment it manages, with the amount of control depending entirely on which hosting plan you chose.

Managed containers

Google Cloud Run

your container image, started on demand and scaled to zero, with requests routed into it.

Docker

an image you build, which means every system library and font is present only because you put it there.

Fly.io

your image running in a lightweight virtual machine, one per instance, started and stopped on demand.

Container orchestration

Kubernetes

the same container as Docker, scheduled onto a node with a memory limit the kernel enforces by killing things.

Platform as a service

Heroku

a slug built by buildpacks from your repository, run on a dyno with an ephemeral filesystem.

Render

either a native runtime built from your repository, or a container built from your Dockerfile.

  • Puppeteer: a native runtime with no package manager
  • Playwright: an install step with nowhere to write

Railway

a build from your repository, either through an automatic builder or your own Dockerfile.

  • Puppeteer: a builder that installs language packages only
  • wkhtmltopdf: an apt package the build never runs

CI runners

GitHub Actions

an ephemeral runner with a lot of memory, a browser already installed, and a job that ends when the workflow does.