Typefold and headless Chrome, measured.
We rendered the same invoice with Typefold and with headless Chrome on the same server, and measured speed, file size, memory and start-up time. Here are all the numbers, including where Chrome wins.
Measured on 14 October 2026.
The short version.
Where Typefold is ahead
- About 4 to 6 times faster than Chrome opening a new page for each document, the usual way to keep documents apart: 24 ms on average against 92 to 152 ms for a one-page invoice.
- About 4 times smaller files: 20 KB against 77 KB for the same invoice.
- Flat memory: the render process grew by less than 1 MB over 1,000 documents. Chrome reusing one page grew by more than 1 GB.
- The same bytes every time: the same request gives a byte-identical PDF.
Where Chrome is ahead
- A warm, reused Chrome page is as fast on a one-page invoice (22 ms each), and about 2.4 times faster on a 13-page document. Reusing one page shares state between documents and kept growing in memory.
- Cold start: from a new process to the first PDF, Chrome takes 550 to 690 ms and Typefold about 790 ms. The hosted service keeps its engine warm, so you don't wait for this.
A one-page invoice.
Median time to render one invoice, one request at a time, after warm-up. Shorter is faster.
| Setup | Median ms | 95th pct. ms | Mean ms | PDFs per second | PDF bytes |
|---|---|---|---|---|---|
| Typefold engine | 22.0 | 34.3 | 23.9 | 41.9 | 19,968 |
| Typefold API, end to end | 86.7 | 108.3 | 87.9 | 11.4 | 19,968 |
| Chrome headless shell, one reused page | 22.0 | 27.0 | 22.1 | 45.2 | 77,359 |
| Chrome headless shell, new page per document | 89.3 | 108.5 | 91.5 | 10.9 | 77,359 |
| Chrome headless shell, new context per document | 90.2 | 105.1 | 90.1 | 11.1 | 77,359 |
| Chrome, one reused page | 39.3 | 46.4 | 39.6 | 25.3 | 77,464 |
| Chrome, new page per document | 149.8 | 177.4 | 152.4 | 6.6 | 77,464 |
| Chrome, new context per document | 159.8 | 183.2 | 160.6 | 6.2 | 77,464 |
"Typefold engine" is the render step alone. "Typefold API, end to end" is a full HTTP call: sign-in check, template, saving the job, queueing, rendering, storing the file and the response. The engine took about 24 ms of those 87 ms. Chrome rows are the bare page.pdf() call, so compare them with the engine row.
A long invoice.
The same template with 200 lines. Chrome with one reused page, its fastest setup, is about 2.4 times faster here.
| Setup | Median ms | 95th pct. ms | Mean ms | PDF bytes |
|---|---|---|---|---|
| Typefold engine (13 pages) | 245.3 | 318.3 | 250.2 | 72,711 |
| Typefold API, end to end (13 pages) | 357.2 | 459.6 | 369.4 | 72,711 |
| Chrome headless shell, one reused page (12 pages) | 102.6 | 135.2 | 105.0 | 111,030 |
| Chrome, one reused page (12 pages) | 116.9 | 152.2 | 121.7 | 111,135 |
The fonts differ (see the notes below), so Typefold lays the document out on 13 pages and Chrome on 12. Part of the gap is the extra page.
Memory over 1,000 documents.
Proportional memory (PSS) in MB, after 20 warm-up renders and after 1,000 more invoices.
| Setup | Before | After 1,000 | Notes |
|---|---|---|---|
| Typefold render process in the running service | 280.1 | 280.7 | It had already rendered about 300 documents before the run. |
| Typefold engine in a new process | 193.9 | 320.0 | The engine's own memory stayed at 27 MB; the rest is the new process settling in. |
| Chrome, new page per document | 267.6 | 273.2 | Eight processes. 191 MB when idle. |
| Chrome, one reused page | 313.0 | 1,436.4 | Grows about 1.1 MB per document. |
Chrome with a new page per document stays flat too, but it is the slow setup above. Chrome's memory is summed over all of its processes.
Cold start.
From starting a new process to having the first invoice, in ms. Median of six runs, with the range.
| Setup | To first PDF | Range | Engine or browser start | First render |
|---|---|---|---|---|
| Typefold | 794 | 771–929 | 181 | 217 |
| Chrome | 691 | 665–761 | 149 | 169 |
| Chrome headless shell | 551 | 499–612 | 70 | 97 |
Loading the code takes about 350 ms on both sides. Typefold's first render is slower because WebAssembly is still being optimised; after warm-up it takes about 22 ms.
Excel workbooks.
A formatted sales workbook through the API, end to end. Chrome has no Excel output.
| Workbook | Median ms | 95th pct. ms | File bytes |
|---|---|---|---|
| Monthly sales, 6 rows | 41.2 | 53.7 | 8,398 |
| Monthly sales, 10,000 rows | 2,623.5 | 2,974.0 | 282,409 |
How we measured.
- Server
- Cloud VM with 4 vCPUs (Intel Xeon, 2.1 GHz) and 16 GB of memory, Linux 6.18
- Runtime
- Node.js 24.22
- Chrome
- Chromium 141 through Playwright 1.63, both the full browser and the headless shell
- Document
- A one-page A4 invoice with four lines, a QR code and a footer with page numbers
- Both sides got the same final HTML and CSS: the exact request Typefold's renderer received after the template was filled. Chrome loaded it with
setContentand printed it withpage.pdf(), with the same page size, margins and footer. - Each speed figure is 200 renders after 20 warm-up renders (50 after 5 for the long invoice and the large workbook), one at a time. We did not measure parallel throughput.
- Chrome ran in three setups: one page reused for every document, a new page per document, and a new browser context per document. The last two keep documents apart, as a service needs to.
- We checked page 1 of every output by eye. Both sides produced the same layout and content.
What to keep in mind.
- The fonts differ. Typefold uses its bundled Geist font; Chrome used Liberation Sans from the server, and drew the footer with Type 3 fonts. Some of the file size difference comes from the fonts. Without the footer, Chrome's file is 58 KB, still about 3 times larger.
- A reused Chrome page is Chrome's best case, not a safe production setup: documents share state, and memory grew with every render.
- Typefold does a little more per render: it checks limits, sets metadata and validates the PDF. It also does less: it runs no JavaScript and fetches nothing from the network. The invoice had neither, so this did not slow Chrome down.
- A shared, busy server. The whole Typefold stack, its database and development servers ran on the same 4 cores during every run, so the 95th percentile figures are probably higher than on a quiet server, on both sides.
- One server, one run. Your numbers will differ with your hardware and documents. Treat the ratios as a guide, not a promise.