Блог

gPdf vs DocRaptor: чому edge rendering перемагає HTML-to-PDF

DocRaptor використовує Prince для HTML-to-PDF на hosted backend. gPdf render structured JSON прямо на Cloudflare edge. Різниця ціни 18×, і це не teaser.

DocRaptor — компетентний product. Він загортає Prince, gold-standard engine для HTML-to-PDF, у hosted REST API з retries, async jobs і добрими docs. Існує понад десятиліття, і для багатьох teams це obvious choice, коли “не хочу запускати Prince сам”.

Ми інший тип tool. gPdf взагалі не приймає HTML; він приймає structured JSON і render PDF безпосередньо на Cloudflare edge. List-price gap для 100K pages/month: $5/mo (gPdf Basic) vs $89/mo (DocRaptor Basic), приблизно 18×. Це не opening promo. Це structural. Ця стаття пояснює, чому structure створює таку price, і де кожен tool реально fit.

Дві архітектури поруч

LayerDocRaptor (HTML → PDF)gPdf (JSON → PDF)
InputHTML + CSS, з Prince extensions for paged mediaJSON DocumentRequest
RendererPrince, compiled C++ engineCustom Rust engine, compiled to WebAssembly
HostingCentralised servers DocRaptor, US datacentre regionCloudflare Workers, кожен CF colo, 300+ cities
Cold startServer-side worker poolV8 isolate boot, single-digit ms
Per-render computeLayout pass over HTML/CSS, потім Prince paginatesDirect typesetting, без layout interpretation pass
Per-render p50~250-800 ms wall-clock, network + render~3-8 ms, network + render
Output determinismHigh, Prince matureByte-identical, same JSON → same bytes

Якщо читати ці two columns як “general HTML printer” проти “purpose-built document renderer”, ви вже зрозуміли architectural decision. Усе інше, latency, cost і навіть feature lists, є downstream від цього choice.

Податок Prince

Prince добрий. Він також робить роботу, яка не потрібна більшості invoice/receipt/label workflows: implement CSS Paged Media для arbitrary HTML, який user може надіслати; page-break rules, running headers, footnotes, cross-references, generated content boxes.

Ця generality має runtime cost. Щоб paginate arbitrary HTML document, engine має:

  1. Parse і validate HTML
  2. Parse і resolve CSS cascade, потенційно з власними Prince extensions
  3. Build render tree
  4. Run multi-pass layout, особливо для tables across pages або balanced columns
  5. Resolve cross-references across pages
  6. Emit PDF objects

Більшість цих passes — це вартість прийняття HTML як input. Якщо input уже structured data, що майже завжди так, бо invoice існує як JSON object до того, як ви wrap його в HTML, ви платите за ці passes у compute і latency на кожному render, а вони не додають value до output.

gPdf повністю пропускає layout-interpretation step. JSON DocumentRequest уже structurally specifies page layout: { pages: [{ size, elements: [...] }] }. Renderer typesets elements, deterministic paginate tables/lists і emit PDF. Немає CSS cascade для resolve, немає float layout для compute, немає cross-reference resolution pass.

Результат: той самий single-page invoice, який займає ~300 ms у DocRaptor, займає ~3 ms у gPdf. Ми швидші не тому, що написали швидший Prince; ми швидші тому, що не робимо більшість того, що робить Prince.

”Занадто дешево, щоб бути правдою” — реальне procurement objection

Це потрібно address directly, бо воно виникає на кожному B2B sales call.

“$5/mo for 100K renders. DocRaptor — $89. Anvil — $0.10/PDF, тобто $10,000 для same volume. Що з вами не так?”

Є три чесні reasons, чому ми можемо charge таку price:

1. Ми не запускаємо browser

DocRaptor amortises Prince infrastructure across customers. gPdf amortises one Cloudflare Worker, який коштує приблизно $0.50/million requests на Workers Bundled. З JSON-shaped input наш renderer займає приблизно 1.5 ms CPU per render. Додайте 50% margin, і ви все ще в cents-per-thousand-renders range. Arithmetic і є price.

2. Ми не запускаємо control plane

Немає async jobs, callbacks, retry queue, document storage, preview-link UI, multi-tenant database. Кожен render — single round-trip до stateless function і назад. Це прибирає весь ops surface, який більшість “PDF API” companies закладає в budget, і саме цей surface виправдовує їхню price.

3. Model сам відсіює workloads, на яких ми втрачали б гроші

Якщо document справді потребує HTML-to-PDF, наприклад 60-page legal contract або complex CSS-Grid report, ви bounce від JSON model у першу hour і підете до DocRaptor. Нам не потрібно price defensively для цих workloads, бо вони self-route. Ми price лише long-but-narrow tail “structured-data-to-document” workloads, де per-render cost справді tiny.

Разом: $5/100K не loss leader; це actual cost-of-goods-sold plus margin. Ми можемо тримати це, бо underlying compute дійсно настільки дешевий, коли ви не ship browser.

Де DocRaptor правильний вибір

Ми намагаємося не писати self-serving comparison. Cases, де DocRaptor справді wins:

  • Ваш input — HTML, який ви не повністю control. User-generated reports, third-party templates, Markdown-from-CMS-rendered-to-HTML. Не варто писати JSON mapper для arbitrary input.
  • Вам потрібні CSS Paged Media features, які supports Prince. Running headers/footers per chapter, complex footnote reflow, named-page selectors, generated tables of contents, indexes. gPdf має structured equivalents для common subset, але якщо ви живете в @page :left selectors, Prince — ваш friend.
  • Ваша content team пише HTML/CSS, а не JSON. Не нав’язуйте JSON authoring workflow non-engineering team. Вони це зненавидять.
  • Async + callbacks + document storage as a service. DocRaptor stores generated PDFs і дає signed URLs для delivery. gPdf strictly stateless; result stores ваш code.

Якщо ви в будь-якому з цих buckets, залишайтесь на DocRaptor. Це правильний tool.

Де gPdf правильний вибір

Дзеркальна ситуація:

  • Ваші inputs уже structured data: database rows, JSON API payloads, queue messages.
  • Latency важлива: interactive checkout flows, real-time label printing, on-demand statement generation.
  • Вам потрібна byte-identical reproducibility для tests, audit trails або e-invoice retention.
  • Ви cost-sensitive на будь-якому volume понад кілька thousand renders/month.
  • Вам потрібні barcodes, як GS1-128, QR, Data Matrix, PDF417, Aztec, MaxiCode, з sub-millimetre precision. Prince technically supports SVG barcodes, але 0.1 mm overall length precision через HTML/CSS non-trivial.
  • Вам потрібні PDF/A (1b/2b/3b/4) або Factur-X / ZUGFeRD attachments for compliance.
  • Ви не хочете запускати JSON-to-HTML-to-PDF pipeline, коли можна запускати JSON-to-PDF pipeline.

Migration механічна, не стратегічна

Поширене worry: “Switching означає rewrite усіх templates.” Зазвичай ні. Most HTML-to-PDF templates — це 20% layout, який один раз стає JSON structure, і 80% data interpolation, що однаковий незалежно від renderer.

Practical path:

  1. Виберіть один document type для migration. Почніть із highest-volume one: biggest savings, smallest blast radius.
  2. Візьміть data interface HTML template, тобто variables, які він interpolates, і напишіть невелику mapToDocumentRequest(data) function.
  3. Iterate у Playground, доки output match.
  4. A/B у production: route 5% traffic до gPdf на два weeks. Diff PDFs. Compare bills.
  5. Roll forward або roll back на основі data, не vibes.

Ми бачили teams, які робили це за один sprint і економили 90% PDF bill наступного місяця. Ми також бачили teams, які розуміли, що їхній workload насправді HTML-to-PDF case, і залишалися на DocRaptor; це теж правильне decision.

TL;DR

DocRaptorgPdf
Best atHTML → PDF для arbitrary contentJSON → PDF для structured documents
Price (100K pages/mo)$89$5
p50 render250-800 ms3-8 ms
Edge-deployedНі, centralisedТак, 300+ Cloudflare colos
Async + storageТак, includedНі, stateless by design
PDF/A + Factur-XЧерез Prince extensionsbuilt-in

Якщо ваші documents — це structured data, одягнена в HTML для renderer, ви платите за translation step, якого не має бути. Спробуйте Playground: describe один invoice у JSON, render у browser менш ніж за 5 ms і подивіться, чи gap збігається з вашим gut feeling.