The document-processing microservice gains a second PDF-rendering path : HTML input is rendered through a headless browser using the W3C WebDriver Print command, served through a pooled Selenium WebDriver fleet. The existing FOP / XSL-FO path stays in place for the workloads it already handles ; the headless-browser path covers the surfaces where the browser's own layout engine is the source of truth.
Why two PDF engines
- FOP / XSL-FO excels at high-volume statutory output — fixed-format invoices, regulated reports, banking documents — where typography, page furniture and pagination are tightly specified by the document schema.
- Headless browser excels at CSS-heavy documents, web-rendered forms, dashboards and any output where the browser's print path is the canonical layout — including documents that originate in HTML and need to ship as PDF without re-typesetting through XSL-FO.
- One API. The endpoint accepts HTML content or a URL ; the service routes internally to the appropriate engine based on the request shape and a routing hint. Application code does not need to know which engine ran.
Browser pool topology
- Firefox primary, Chromium fallback. Both browsers ship in the microservice container ; Firefox is the default because its WebDriver Print honours the broadest set of CSS print specifications, and Chromium covers the cases where Firefox fails — typically heavy JavaScript content or vendor-prefixed CSS.
- Pooled WebDriver sessions. Sessions are leased per request from a pool sized to the available CPU ; pool exhaustion blocks rather than failing so the back-end behaviour is bounded under load spikes.
- Container-architecture agnostic. Both browsers run on x86_64 and ARM64 images, so the microservice deploys to Graviton hosts without a separate build path.
Wire protocol parity
The endpoint is exposed over both HTTP and gRPC, on the same microservice surface as FOP, XSLT, OCR and the Mermaid diagram service — one mesh, one wire protocol family. Existing platform code that calls the FOP renderer ports to the headless-browser renderer by changing the request hint ; the response envelope, error shape and observability surface are identical.