DocRaptor एक सक्षम product है. यह Prince, HTML-to-PDF का gold-standard engine, को hosted REST API में wrap करता है, retries, async jobs और अच्छी docs के साथ. यह एक decade से अधिक समय से है, और कई teams के लिए “मैं Prince खुद नहीं चलाना चाहता” वाली obvious choice है.
हम अलग तरह का tool हैं. gPdf HTML बिल्कुल नहीं लेता; यह structured JSON लेता है और Cloudflare edge पर सीधे PDF render करता है. 100K pages/month पर list-price gap है: $5/mo (gPdf Basic) vs $89/mo (DocRaptor Basic), यानी करीब 18×. यह opening promo नहीं है. यह structural है. यह post बताती है कि क्यों structure उस price को पैदा करता है, और हर tool वास्तव में कहाँ fit होता है.
दो architectures साथ-साथ
| Layer | DocRaptor (HTML → PDF) | gPdf (JSON → PDF) |
|---|---|---|
| Input | HTML + CSS, Prince extensions for paged media के साथ | JSON DocumentRequest |
| Renderer | Prince, compiled C++ engine | Custom Rust engine, WebAssembly में compiled |
| Hosting | DocRaptor के centralised servers, US datacentre region | Cloudflare Workers, हर CF colo, 300+ cities |
| Cold start | Server-side worker pool | V8 isolate boot, single-digit ms |
| Per-render compute | HTML/CSS पर layout pass, फिर Prince pagination | Direct typesetting, कोई layout interpretation pass नहीं |
| 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 |
अगर आप इन columns को “general HTML printer” बनाम “purpose-built document renderer” के रूप में पढ़ते हैं, तो architectural decision समझ आ गया. बाकी सब, latency, cost और feature lists तक, उसी choice से निकलता है.
Prince tax
Prince अच्छा है. लेकिन यह वह काम भी करता है जिसकी अधिकांश invoice/receipt/label workflows को जरूरत नहीं: arbitrary HTML के लिए CSS Paged Media implement करना, जैसे page-break rules, running headers, footnotes, cross-references और generated content boxes.
उस generality की runtime cost है. Arbitrary HTML document को paginate करने के लिए engine को:
- HTML parse और validate करना होता है
- CSS cascade parse और resolve करनी होती है, शायद Prince की अपनी extensions के साथ
- Render tree build करनी होती है
- Multi-pass layout चलाना होता है, खासकर page-span tables या balanced columns के लिए
- Pages के बीच cross-references resolve करने होते हैं
- PDF objects emit करने होते हैं
इन passes में से ज्यादातर HTML को input के रूप में स्वीकार करने की लागत हैं. अगर input पहले से structured data है, जो लगभग हमेशा होता है क्योंकि invoice कहीं JSON object के रूप में रहता है, तो आप हर render पर compute और latency में उन passes की कीमत चुका रहे हैं, और वे output में value नहीं जोड़ते.
gPdf layout-interpretation step पूरी तरह छोड़ देता है. JSON DocumentRequest पहले से page layout structurally specify करता है: { pages: [{ size, elements: [...] }] }. Renderer elements typeset करता है, tables/lists को deterministic तरीके से paginate करता है, और PDF emit करता है. CSS cascade resolve नहीं करनी, float layout compute नहीं करना, cross-reference resolution pass नहीं.
परिणाम: वही single-page invoice जो DocRaptor पर ~300 ms लेता है, gPdf पर ~3 ms लेता है. हम इसलिए तेज नहीं हैं कि हमने तेज Prince लिखा; हम इसलिए तेज हैं कि Prince जो करता है उसका बड़ा हिस्सा हम करते ही नहीं.
”इतना सस्ता कि सच न लगे” procurement में वास्तविक objection है
इसे सीधे address करना जरूरी है, क्योंकि यह हर B2B sales call में आता है.
“$5/mo for 100K renders. DocRaptor $89 है. Anvil $0.10/PDF है, यानी same volume के लिए $10,000. आप लोगों में क्या गलत है?”
तीन ईमानदार कारण हैं जिनसे हम यह charge कर सकते हैं:
1. हम browser नहीं चलाते
DocRaptor Prince infrastructure को customers के बीच amortise करता है. gPdf एक Cloudflare Worker को amortise करता है, जिसकी cost Workers Bundled पर लगभग $0.50/million requests है. 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 stateless function तक एक round-trip है और वापस. इससे वह पूरा ops surface हट जाता है जिसके लिए अधिकांश “PDF API” companies budget करती हैं, और वही surface उनकी price justify करता है.
3. Model उन workloads को self-select कर देता है जिन पर हम नुकसान करेंगे
अगर आपका document सच में HTML-to-PDF चाहता है, जैसे 60-page legal contract या complex CSS-Grid report, तो आप पहले hour में JSON model से bounce होकर DocRaptor पर चले जाएँगे. हमें उन workloads के लिए defensively price नहीं करना पड़ता क्योंकि वे self-route करते हैं. हमें सिर्फ “structured-data-to-document” workloads की long-but-narrow tail के लिए price करना है, जहाँ per-render cost सच में tiny है.
साथ मिलाकर: $5/100K कोई loss leader नहीं है; यह actual cost-of-goods-sold plus margin है. हम इसे वहीं रख सकते हैं क्योंकि underlying compute इतना ही सस्ता है जब आप browser ship नहीं करते.
जहाँ DocRaptor सही choice है
हम self-serving comparison नहीं लिखना चाहते. जहाँ DocRaptor सच में जीतता है:
- आपका input ऐसा HTML है जिसे आप पूरी तरह control नहीं करते. User-generated reports, third-party templates, CMS से Markdown-to-HTML output. Arbitrary input के लिए JSON mapper लिखना सही काम नहीं.
- आपको Prince-supported CSS Paged Media features चाहिए. Running headers/footers per chapter, complex footnote reflow, named-page selectors, generated tables of contents, indexes. gPdf common subset के structured equivalents देता है, लेकिन अगर आप
@page :leftselectors में रहते हैं, तो Prince आपका दोस्त है. - आपकी content team HTML/CSS लिखती है, JSON नहीं. Non-engineering team पर JSON authoring workflow मत थोपिए. वे इसे पसंद नहीं करेंगे.
- Async + callbacks + document storage as a service. DocRaptor generated PDFs store करता है और delivery के लिए signed URLs देता है. gPdf strictly stateless है; result आपका code store करता है.
अगर आप इनमें से किसी bucket में हैं, DocRaptor पर रहें. वही सही tool है.
जहाँ gPdf सही choice है
Mirror image:
- आपके inputs पहले से structured data हैं, जैसे database rows, JSON API payloads या queue messages.
- Latency मायने रखती है, जैसे interactive checkout flows, real-time label printing, on-demand statement generation.
- Tests, audit trails या e-invoice retention के लिए byte-identical reproducibility चाहिए.
- कुछ thousand renders/month से ऊपर किसी भी volume पर cost sensitivity है.
- आपको GS1-128, QR, Data Matrix, PDF417, Aztec, MaxiCode जैसे barcodes sub-millimetre precision पर चाहिए. Prince technically SVG barcodes support करता है, लेकिन HTML/CSS के जरिए 0.1 mm overall length precision non-trivial है.
- आपको compliance के लिए PDF/A (1b/2b/3b/4) या Factur-X / ZUGFeRD attachments चाहिए.
- आप JSON-to-HTML-to-PDF pipeline नहीं चलाना चाहते जब JSON-to-PDF pipeline चल सकती है.
Migration mechanical है, strategic नहीं
Common worry है: “Switching का मतलब हमारे सारे templates rewrite करना है.” आम तौर पर ऐसा नहीं होता. Most HTML-to-PDF templates 20% layout हैं, जो एक बार JSON structure बन जाता है, और 80% data interpolation, जो renderer कोई भी हो एक जैसा रहता है.
Practical path:
- migrate करने के लिए एक document type चुनें. Highest-volume one से शुरू करें, सबसे बड़ी saving और सबसे छोटा blast radius.
- HTML template का data interface लें, यानी variables जिन्हें वह interpolate करता है, और छोटी
mapToDocumentRequest(data)function लिखें. - Playground में iterate करें जब तक output match न करे.
- Production में A/B करें: दो weeks के लिए 5% traffic gPdf पर route करें. PDFs diff करें. Bills compare करें.
- Data के आधार पर roll forward या roll back करें, vibes के आधार पर नहीं.
हमने teams को एक sprint में यह करते और अगले महीने PDF bill का 90% बचाते देखा है. हमने teams को यह भी महसूस करते देखा कि उनका workload सच में HTML-to-PDF case था और वे DocRaptor पर रहे; वह भी सही decision था.
TL;DR
| DocRaptor | gPdf | |
|---|---|---|
| Best at | Arbitrary content के लिए HTML → PDF | Structured documents के लिए JSON → PDF |
| Price (100K pages/mo) | $89 | $5 |
| p50 render | 250-800 ms | 3-8 ms |
| Edge-deployed | नहीं, centralised | हाँ, 300+ Cloudflare colos |
| Async + storage | हाँ, included | नहीं, stateless by design |
| PDF/A + Factur-X | Prince extensions के जरिए | built-in |
अगर आपके documents renderer के लिए HTML बने structured data हैं, तो आप उस translation step के लिए pay कर रहे हैं जिसका होना जरूरी नहीं. Playground try करें: अपनी invoices में से एक को JSON में describe करें, browser में 5 ms से कम में render करें, और देखें gap आपकी intuition से match करता है या नहीं.