PDFPipe

Platform as a service / Render

Puppeteer on Render: a native runtime with no package manager

On a native runtime service the browser fails to start with missing shared libraries and there is no way to install them.

What is actually wrong

A native runtime gives you a language toolchain, not a machine. There is no root and no apt, so the twenty or so libraries Chromium links against cannot be added. This is a deliberate property of that deployment mode rather than a gap, and it is the reason the browser cannot run there at all.

What Render gives you to work with

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

  • Packaging: no explicit size limit. The native runtime is the constraint instead: it gives you a language runtime and not a package manager, so system libraries cannot be added to it.
  • Filesystem: writable and ephemeral unless a persistent disk is attached. A disk changes the deployment to a single instance, which matters if the render workload is what you were scaling.
  • Processes: full control in a container service. The smaller instance sizes have well under a gigabyte of memory, which a browser exhausts on a large document.

The fix, if you are keeping Puppeteer

Switch the service to a Docker deployment and install the dependencies in the image, which is the same Dockerfile as any other container platform. Then size the instance for a browser: the smaller instance types have well under a gigabyte of memory and a browser rendering a large document will exhaust that.

What still hurts after that

Moving to a Dockerfile means owning the base image, its security updates and its font set. Instance sizing is the ongoing cost: a browser needs the memory reserved whether or not a document is being rendered, so an endpoint that renders a few hundred documents a day pays for browser-sized capacity all day.

What Puppeteer is genuinely good at

it renders exactly what a browser renders, which means modern CSS, web fonts and client-side JavaScript all behave the way they do in a tab. That is worth keeping in view: the problem on this page is where it runs, not what it produces. Puppeteer is a Node library that drives a real Chromium, and downloads that Chromium into node_modules when it is installed. It needs the browser binary, a long list of shared libraries the browser links against, fonts, and enough memory for a browser process that is not accounted for by your runtime's heap settings.

The other shape of the answer

Every fix above keeps the renderer inside your deployment, which means the constraint stays yours: the package size, the shared libraries, the fonts, the memory, the patching. The alternative is an HTTP call from Render to something that already has a browser in it, which turns all of the above into a request and a response. That is what this API is, and it is the reason these pages exist. Whether that trade is right depends on whether rendering is a thing you want to operate.

Frequently asked

Can Puppeteer run on Render at all?

Switch the service to a Docker deployment and install the dependencies in the image, which is the same Dockerfile as any other container platform. Then size the instance for a browser: the smaller instance types have well under a gigabyte of memory and a browser rendering a large document will exhaust that. Whether that is worth doing is a separate question from whether it is possible, and the section above on what still hurts is the honest answer to it.

Why does it work locally?

Because a development machine has root, a package manager, several gigabytes of memory, a full font set and no packaging limit. Every one of those is a thing Render constrains. A renderer that works locally and fails on deploy has not regressed: it has met the first environment that does not give it everything.

Related failures

The same platform with a different renderer, and the same renderer on other platforms.

If the render moves off this platform, none of the above is your problem to keep solving. 100 free documents a month, and a playground that needs no signup.