The Container You Have to Babysit
You need to generate PDFs from your application. Invoices, reports, contracts, certificates. You search for options and find Gotenberg — an open-source Docker container that wraps Chromium and LibreOffice behind a REST API. Send HTML, get a PDF. Send a DOCX, get a PDF. Clean abstraction over messy tools.
So you docker pull gotenberg/gotenberg, add it to your compose file, and it works. For a while.
Then you notice the container eats 500 MB of RAM at idle because it’s running Chromium and LibreOffice. You need custom fonts, so you build a custom Docker image with your font files baked in. Chromium gets a CVE, so you rebuild and redeploy. Traffic spikes and you need to scale — but each instance carries the full weight of a browser and an office suite. You set up health checks because Chromium occasionally hangs.
None of this is Gotenberg’s fault. It’s the nature of wrapping desktop applications in containers and calling them APIs.
What Gotenberg Actually Does
Gotenberg is a well-built project. It takes Chromium and LibreOffice — two powerful but heavy rendering engines — and exposes them through a stateless HTTP API. The core operations:
- HTML to PDF. Chromium renders your HTML and prints it to PDF. You control headers, footers, margins, and page size.
- URL to PDF. Same thing, but Chromium navigates to a URL first.
- Office to PDF. LibreOffice converts DOCX, XLSX, PPTX, ODT, and other formats to PDF.
- PDF merging. Combine multiple PDFs into one.
The Docker image ships with both engines pre-installed. You get one container that handles all these conversions. The API is straightforward — multipart form requests with your source files and conversion parameters.
The limitation is in the architecture. Gotenberg converts to PDF. It doesn’t generate documents from data. You still need to produce the HTML or Office file that Gotenberg then converts. That means you’re writing HTML templates (with all the CSS-for-print quirks that entails) or generating DOCX files with another library before handing them to Gotenberg for the final PDF conversion.
And the output is always PDF. Need a DOCX? Gotenberg can convert Office files to PDF, but it can’t generate a DOCX from structured data. Need an EPUB for a publication workflow? That’s a different tool entirely.
The Infrastructure Tax
Running Gotenberg means running Docker. For teams already operating containerized infrastructure, that’s not a big ask. But the container itself is heavier than most.
The Gotenberg Docker image weighs in north of 1 GB. It bundles a full Chromium installation, a full LibreOffice installation, and the Go binary that orchestrates them. Each running container needs enough memory for both engines — Chromium alone can spike to several hundred MB per render, and LibreOffice is similarly hungry.
Scaling means running more of these heavy containers. If you’re generating 50 invoices at the end of the month, one instance is fine. If you’re generating thousands of documents per hour, you’re managing a fleet of containers each carrying a browser and an office suite.
Then there’s the maintenance:
- Chromium security patches. Chromium is a browser. Browsers get CVEs regularly. When Gotenberg updates Chromium, you need to pull the new image and redeploy.
- Font management. Want your corporate typeface in generated PDFs? Build a custom Docker image that installs the fonts at the OS level. Every font change means a new image build.
- LibreOffice rendering fidelity. Office-to-PDF conversion relies on LibreOffice’s rendering engine, which doesn’t always match Microsoft Office’s output. Complex spreadsheets, embedded charts, and advanced formatting can shift during conversion.
- Health monitoring. Chromium can hang, leak memory, or crash. You need health checks and restart policies to keep the service reliable.
This is all standard infrastructure work. If you have a platform team and Kubernetes, it’s routine. If you’re a small team shipping a product, it’s overhead that has nothing to do with your actual business logic.
Structured Content Instead of HTML
The Iteration Layer Document Generation API takes a different approach entirely. Instead of converting HTML or Office files to PDF, you describe your document as structured JSON — content blocks, styles, page configuration — and the API renders it into the format you choose.
No Chromium. No LibreOffice. No Docker. No HTML templates with CSS print stylesheets. You send a JSON payload, you get back a document.
The API supports four output formats from the same content definition: PDF, DOCX, EPUB, and PPTX. One content model, four outputs. An invoice that renders as a PDF for the customer can also render as a DOCX for internal editing — same API call, different format parameter.
The content model gives you block types like headlines, paragraphs (with Markdown), tables, grids, images, separators, QR codes, barcodes, page breaks, table of contents, and lists. You compose these blocks into a document, define styles at the document level, and the API handles rendering.
What the API Looks Like
Here’s an invoice — company info in a two-column grid, line items in a table, and a barcode at the bottom — built with the TypeScript SDK:
import { IterationLayer } from "iterationlayer";
const client = new IterationLayer({ apiKey: "YOUR_API_KEY" });
const result = await client.generateDocument({
format: "pdf",
document: {
metadata: { title: "Invoice #2024-0042" },
page: {
size: { preset: "A4" },
margins: { top_in_pt: 72, right_in_pt: 72, bottom_in_pt: 72, left_in_pt: 72 },
},
styles: { /* ... */ },
content: [
{ type: "grid", columns: [
{ column_span: 6, blocks: [
{ type: "headline", level: "h2", text: "Acme Corp" },
{ type: "paragraph", markdown: "123 Business St, Suite 100" },
]},
{ column_span: 6, horizontal_alignment: "right", blocks: [
{ type: "headline", level: "h2", text: "Invoice #2024-0042" },
{ type: "paragraph", markdown: "Date: 2024-12-15" },
]},
]},
{ type: "separator" },
{ type: "table",
header: { cells: [{ text: "Item" }, { text: "Qty" }, { text: "Price" }, { text: "Total" }] },
rows: [
{ cells: [{ text: "API Credits" }, { text: "10,000" }, { text: "$0.01" }, { text: "$100.00" }] },
]},
{ type: "barcode", value: "INV20240042", format: "code128",
width_in_pt: 200, height_in_pt: 40,
fg_hex_color: "#1a1a1a", bg_hex_color: "#ffffff" },
],
},
});
One request. No template files. No Chromium rendering. The document structure is the template — defined in code, version-controlled alongside your application, and testable without spinning up a container.
Change format: "pdf" to format: "docx" and you get the same invoice as a Word document. The Gotenberg equivalent would require two entirely different pipelines — one for HTML-to-PDF and a separate tool to generate DOCX.
Features You Don’t Have to Build
Gotenberg converts files. It doesn’t generate content. That means anything beyond basic HTML rendering requires you to build it yourself or bring in additional tools.
Headers and footers. Iteration Layer supports document-level headers and footers with page numbers, dates, and custom text. In Gotenberg, you configure headers and footers through Chromium’s print options — which means writing more HTML for the header/footer templates and dealing with their separate rendering context.
Table of contents. Add a { type: "table-of-contents" } block and the API generates a TOC from your headlines. In an HTML-to-PDF pipeline, you’d need JavaScript to scan headings, build anchor links, and calculate page numbers — if Chromium even exposes page numbers to your script.
QR codes and barcodes. Dedicated block types for QR codes and six barcode formats (Code 128, Code 39, EAN-13, EAN-8, Codabar, ITF). The invoice example above includes a Code 128 barcode in one line of JSON. With Gotenberg, you’d generate the barcode with a JavaScript or server-side library, render it as an SVG or image, and embed it in your HTML.
19 page size presets. A4, Letter, Legal, Tabloid, and 15 more — including envelope sizes. Set preset: "A4" instead of calculating millimeter dimensions.
Custom fonts via URL. Point the API at a font file and reference it in your styles. No Docker image rebuilds, no OS-level font installation.
Side-by-Side
| Capability | Gotenberg | Iteration Layer |
|---|---|---|
| Infrastructure | Self-hosted Docker container | Managed API |
| Rendering engine | Chromium + LibreOffice | Native document renderer |
| Input | HTML, URLs, Office files | Structured JSON content |
| Output formats | PDF only | PDF, DOCX, EPUB, PPTX |
| Content model | None — you provide source files | Structured block types |
| Headers/footers | Chromium print options | Built-in with page numbers |
| Table of contents | Not available | Built-in block type |
| QR codes | Requires external generation | Built-in block type |
| Barcodes | Requires external generation | 6 formats built-in |
| Custom fonts | OS-level install in Docker | Via URL reference |
| Page sizes | Manual dimensions | 19 presets |
| Scaling | More Docker containers | Managed by the API |
| Cost | Free (plus infrastructure) | API usage |
| Data residency | Wherever you host it | EU-hosted (Frankfurt) |
When Gotenberg Makes Sense
Gotenberg is free, open source, and battle-tested. If your team already runs Docker infrastructure and your use case is straightforward HTML-to-PDF conversion, it’s a solid choice. You get full control over the environment, no external API dependency, and zero per-document cost beyond your own compute.
It’s also the right tool if you need Office-to-PDF conversion specifically. If users upload Word documents and you need to convert them to PDF, Gotenberg does this well — you’re using LibreOffice for what LibreOffice is designed to do.
And if your document templates are already built as HTML with CSS print stylesheets, Gotenberg lets you render them without rewriting anything.
When to Use Iteration Layer
If you’re generating documents from application data — invoices, reports, contracts, certificates, ebooks — the structured content model is simpler than writing and maintaining HTML templates. Your document definition lives in code, not in template files. You get four output formats from one content model. And you don’t manage any infrastructure.
The tradeoff is clear: Gotenberg gives you a free, self-hosted conversion engine with the full power (and full weight) of Chromium and LibreOffice. Iteration Layer gives you a managed API that generates documents from structured data — no containers, no browser engines, no font installation.
Get Started
Check the docs for the full block type reference, style options, page configuration, and SDK guides. The TypeScript and Python SDKs handle authentication and response parsing — your first document is a few lines of code.
Document Generation is part of a composable suite — chain it with Document Extraction to parse documents and automatically generate formatted output, all through one credit pool.