Blog

gPdf vs DocRaptor: edge rendering neden HTML-to-PDF'i yener

DocRaptor, HTML'i PDF'e çevirmek için hosted backend'de Prince kullanır. gPdf structured JSON'u doğrudan Cloudflare edge'de render eder. Fiyat farkı 18× ve bu teaser değildir.

DocRaptor yetkin bir üründür. HTML-to-PDF’in gold-standard engine’i olan Prince’i hosted REST API içine sarar; retries, async jobs ve iyi docs sağlar. On yılı aşkın süredir var ve birçok team için “Prince’i kendim çalıştırmak istemiyorum” durumunda obvious choice’tur.

Biz farklı bir tool shape’iyiz. gPdf hiç HTML almaz; structured JSON alır ve Cloudflare edge’de doğrudan PDF render eder. ayda 100.000 sayfa list-price gap: 5 USD/ay (gPdf Basic) vs 89 USD/ay (DocRaptor Basic), yaklaşık 18×. Bu opening promo değildir. Structural’dır. Bu post neden bu structure’ın o price’ı ürettiğini ve her tool’un gerçekte nereye fit ettiğini açıklar.

İki mimari yan yana

Layer DocRaptor (HTML → PDF) gPdf (JSON → PDF)
Input HTML + CSS, Prince extensions for paged media ile JSON DocumentRequest
Renderer Prince, compiled C++ engine Custom Rust engine, WebAssembly’a compiled
Hosting DocRaptor centralised servers, US datacentre region Cloudflare Workers, her CF colo, 300+ cities
Cold start Server-side worker pool V8 isolate boot, single-digit ms
Per-render compute HTML/CSS üzerinde layout pass, sonra Prince pagination Direct typesetting, layout interpretation pass yok
Per-render p50 ~250-800 ms wall-clock, network + render ~3-8 ms, network + render
Output determinism High, Prince mature Byte-identical, same JSON → same bytes

Bu iki column’u “general HTML printer” ve “purpose-built document renderer” diye okursanız architectural decision’ı anlamış olursunuz. Geri kalan her şey, latency, cost ve feature lists dahil, o choice’ın downstream sonucudur.

Prince vergisi

Prince iyidir. Ayrıca çoğu invoice/receipt/label workflow’unun ihtiyaç duymadığı işi yapar: user’ın gönderebileceği arbitrary HTML için CSS Paged Media implement etmek; page-break rules, running headers, footnotes, cross-references, generated content boxes.

Bu generality’nin runtime cost’u vardır. Arbitrary HTML document’ı paginate etmek için engine şunları yapmak zorunda:

  1. HTML’i parse ve validate etmek
  2. CSS cascade’i parse ve resolve etmek, muhtemelen Prince’in kendi extensions’larıyla
  3. Render tree build etmek
  4. Multi-pass layout çalıştırmak, özellikle pages across tables veya balanced columns için
  5. Pages arasında cross-references resolve etmek
  6. PDF objects emit etmek

Bu passes’ın çoğu HTML’i input olarak kabul etmenin maliyetidir. Input zaten structured data ise, ki genelde öyledir çünkü invoice HTML’e wrap edilmeden önce bir yerde JSON object olarak vardır, her render’da compute ve latency olarak bu passes’ın bedelini ödersiniz ve output’a value eklemezler.

gPdf layout-interpretation step’ini tamamen atlar. JSON DocumentRequest page layout’u zaten structurally specify eder: { pages: [{ size, elements: [...] }] }. Renderer elements typeset eder, tables/lists’i deterministic şekilde paginate eder ve PDF emit eder. Resolve edilecek CSS cascade yok, compute edilecek float layout yok, cross-reference resolution pass yok.

Sonuç: DocRaptor’da ~300 ms süren aynı single-page invoice gPdf’te ~3 ms sürer. Daha hızlıyız çünkü daha hızlı Prince yazdık değil; daha hızlıyız çünkü Prince’in yaptığı şeylerin çoğunu yapmıyoruz.

“Gerçek olamayacak kadar ucuz” gerçek bir procurement itirazıdır

Bunu doğrudan ele almak gerekir, çünkü her B2B sales call’da karşımıza çıkar.

“5 USD/ay for 100.000 render. DocRaptor 89. Anvil 0.10/PDF, yani aynı volume için $10,000. Sizinle ilgili sorun ne?”

Bunu charge edebilmemizin üç dürüst nedeni var:

1. Browser çalıştırmıyoruz

DocRaptor Prince infrastructure’ını customers arasında amortise eder. gPdf ise bir Cloudflare Worker’ı amortise eder; Workers Bundled’da maliyeti yaklaşık $0.50/million requests. JSON-shaped input ile renderer’ımız yaklaşık 1.5 ms CPU per render alır. Üzerine %50 margin koysanız bile cents-per-thousand-renders range’inde kalırsınız. Aritmetik fiyatın kendisidir.

2. Control plane çalıştırmıyoruz

Async jobs yok, callbacks yok, retry queue yok, document storage yok, preview-link UI yok, multi-tenant database yok. Her render stateless function’a tek round-trip ve dönüşten ibarettir. Bu, çoğu “PDF API” şirketinin bütçelediği tüm ops surface’i kaldırır; aynı surface onların price’ını justify eder.

3. Model zarar edeceğimiz iş yüklerini kendisi dışarı iter

Belge gerçekten HTML-to-PDF istiyorsa, örneğin 60 sayfalık legal contract veya complex CSS-Grid report, ilk saat içinde JSON modelinden çıkar ve DocRaptor’a gidersiniz. Bu iş yükleri için defensive pricing yapmamız gerekmez, çünkü kendilerini doğru araca yönlendirirler. Yalnızca “structured-data-to-document” iş yüklerinin uzun ama dar kuyruğu için price etmemiz gerekir; burada per-render cost gerçekten çok küçüktür.

Toplamda: $5/100.000 loss leader değildir; actual cost-of-goods-sold plus margin’dir. Browser ship etmediğinizde underlying compute gerçekten bu kadar ucuz olduğu için bunu sürdürebiliriz.

DocRaptor nerede doğru seçimdir

Self-serving comparison yazmamaya çalışıyoruz. DocRaptor’ın gerçekten kazandığı cases:

  • Input tamamen control etmediğiniz HTML ise. User-generated reports, third-party templates, CMS’ten Markdown-to-HTML output. Arbitrary input için JSON mapper yazmak istemezsiniz.
  • Prince’in support ettiği CSS Paged Media features’a ihtiyacınız varsa. Running headers/footers per chapter, complex footnote reflow, named-page selectors, generated tables of contents, indexes. gPdf common subset için structured equivalents sunar, ama @page :left selectors içinde yaşıyorsanız Prince sizin dostunuzdur.
  • Content team’iniz HTML/CSS yazar, JSON değil. Non-engineering team’e JSON authoring workflow dayatmayın. Bundan nefret ederler.
  • Async + callbacks + document storage as a service. DocRaptor generated PDFs’i store eder ve delivery için signed URLs verir. gPdf strictly stateless’tir; sonucu sizin code’unuz store eder.

Bu buckets’tan birindeyseniz, DocRaptor’da kalın. Doğru tool odur.

gPdf nerede doğru seçimdir

Ters görüntü:

  • Inputs zaten structured data: database rows, JSON API payloads, queue messages.
  • Latency önemlidir: interactive checkout flows, real-time label printing, on-demand statement generation.
  • Tests, audit trails veya e-invoice retention için byte-identical reproducibility önemlidir.
  • Birkaç thousand renders/month üstündeki her volume’da cost-sensitive’sinizdir.
  • GS1-128, QR, Data Matrix, PDF417, Aztec, MaxiCode gibi barcodes’u sub-millimetre precision ile üretmeniz gerekir. Prince technically SVG barcodes support eder, ama HTML/CSS üzerinden 0.1 mm overall length precision non-trivial’dır.
  • Compliance için PDF/A (1b/2b/3b/4) veya Factur-X / ZUGFeRD attachments gerekir.
  • JSON-to-PDF pipeline çalıştırabilecekken JSON-to-HTML-to-PDF pipeline çalıştırmak istemezsiniz.

Migration mekaniktir, stratejik değil

Yaygın endişe: “Switch etmek tüm templates’i rewrite etmek demek.” Genelde değil. Çoğu HTML-to-PDF template %20 layout’tur, bu bir kez JSON structure olur, ve %80 data interpolation’dır, renderer ne alırsa alsın aynıdır.

Practical path:

  1. Migrate etmek için tek document type seçin. Highest-volume olanla başlayın; biggest savings, smallest blast radius.
  2. HTML template’in data interface’ini, yani interpolate ettiği variables’ı alın ve küçük bir mapToDocumentRequest(data) function yazın.
  3. Output match edene kadar Playground’da iterate edin.
  4. Production’da A/B yapın: traffic’in %5’ini iki hafta gPdf’e route edin. PDFs diff edin. Bills compare edin.
  5. Vibes’a değil data’ya göre roll forward veya roll back yapın.

Teams’in bunu tek sprint’te yapıp sonraki ay PDF bill’inin %90’ını cebine koyduğunu gördük. Workload’unun gerçekten HTML-to-PDF case olduğunu fark edip DocRaptor’da kalan teams de gördük; bu da doğru decision’dı.

TL;DR

DocRaptor gPdf
Best at Arbitrary content için HTML → PDF Structured documents için JSON → PDF
Fiyat (ayda 100.000 sayfa) $89 $5
p50 render 250-800 ms 3-8 ms
Edge-deployed Hayır, centralised Evet, 300+ Cloudflare colos
Async + storage Evet, included Hayır, stateless by design
PDF/A + Factur-X Prince extensions üzerinden built-in

Documents’ınız renderer için HTML giydirilmiş structured data ise, var olması gerekmeyen translation step için ödeme yapıyorsunuz. Playground’ı deneyin: invoices’larınızdan birini JSON ile describe edin, browser’da 5 ms altında render edin ve gap’in gut feeling’inizle uyuşup uyuşmadığını görün.