DocRaptor เป็น product ที่มีความสามารถ มัน wrap Prince ซึ่งเป็น gold-standard engine ของ HTML-to-PDF ไว้ใน hosted REST API พร้อม retries, async jobs และ docs ที่ดี มีอยู่มานานกว่าทศวรรษ และสำหรับหลาย teams มันคือ choice ที่ชัดเจนเมื่อไม่อยาก run Prince เอง
เราเป็น tool คนละรูปแบบ gPdf ไม่รับ HTML เลย แต่รับ structured JSON แล้ว render PDF โดยตรงที่ Cloudflare edge ส่วนต่าง list price ที่ 100K pages/month คือ $5/mo (gPdf Basic) vs $89/mo (DocRaptor Basic) หรือประมาณ 18× ส่วนต่างนี้ไม่ใช่ opening promo แต่เป็น structural บทความนี้อธิบายว่า ทำไม structure จึงทำให้เกิด price นี้ และแต่ละ tool เหมาะกับอะไรจริง ๆ
สองสถาปัตยกรรม วางเทียบกัน
| Layer | DocRaptor (HTML → PDF) | gPdf (JSON → PDF) |
|---|---|---|
| Input | HTML + CSS พร้อม Prince extensions สำหรับ paged media | JSON DocumentRequest |
| Renderer | Prince, compiled C++ engine | Custom Rust engine, compiled เป็น WebAssembly |
| Hosting | Centralised servers ของ DocRaptor ใน US datacentre region | Cloudflare Workers ทุก CF colo, 300+ cities |
| Cold start | Server-side worker pool | V8 isolate boot, single-digit ms |
| Per-render compute | Layout pass บน HTML/CSS แล้ว Prince paginate | Direct typesetting ไม่มี layout interpretation pass |
| Per-render p50 | ~250-800 ms wall-clock, network + render | ~3-8 ms, network + render |
| Output determinism | สูง เพราะ Prince mature | Byte-identical, same JSON → same bytes |
ถ้าอ่านสอง column นี้เป็น “general HTML printer” เทียบกับ “purpose-built document renderer” คุณเข้าใจ architectural decision แล้ว ส่วนอื่น ๆ ทั้ง latency, cost และ feature lists เป็นผลตามมาจาก choice นี้
ภาษี Prince
Prince ดี แต่มันทำงานที่ invoice/receipt/label workflows ส่วนใหญ่ไม่ต้องการด้วย นั่นคือ implement CSS Paged Media เช่น page-break rules, running headers, footnotes, cross-references และ generated content boxes สำหรับ arbitrary HTML ที่ user ส่งเข้ามา
Generality นี้มี runtime cost เพื่อ paginate arbitrary HTML document engine ต้อง:
- Parse และ validate HTML
- Parse และ resolve CSS cascade อาจรวม Prince extensions
- Build render tree
- Run multi-pass layout โดยเฉพาะ tables ที่ข้าม pages หรือ columns ที่ต้อง balance
- Resolve cross-references ข้าม pages
- Emit PDF objects
Passes ส่วนใหญ่คือ ต้นทุนของการรับ HTML เป็น input ถ้า input ของคุณเป็น structured data อยู่แล้ว ซึ่งแทบจะเป็นจริงเสมอ เพราะ invoice มักมีอยู่เป็น JSON object ก่อนจะ wrap เป็น HTML คุณกำลังจ่าย compute และ latency ของ passes เหล่านี้ในทุก render โดยไม่ได้เพิ่ม value ต่อ output
gPdf ข้าม layout-interpretation step ทั้งหมด JSON DocumentRequest ระบุ page layout เชิงโครงสร้างอยู่แล้ว เช่น { pages: [{ size, elements: [...] }] } Renderer typeset elements, paginate tables/lists แบบ deterministic แล้ว emit PDF ไม่มี CSS cascade ให้ resolve ไม่มี float layout ให้ compute ไม่มี cross-reference resolution pass
ผลลัพธ์: invoice หน้าเดียวที่ใช้ ~300 ms บน DocRaptor ใช้ ~3 ms บน gPdf เราไม่ได้เร็วกว่าเพราะเขียน Prince ที่เร็วกว่า แต่เร็วกว่าเพราะเรา ไม่ทำ ส่วนใหญ่ที่ Prince ทำ
”ถูกเกินจริง” เป็น procurement objection ที่เกิดขึ้นจริง
ต้องตอบเรื่องนี้ตรง ๆ เพราะมันเกิดในทุก B2B sales call
“$5/mo สำหรับ 100K renders. DocRaptor $89. Anvil $0.10/PDF หรือ $10,000 สำหรับ volume เดียวกัน. พวกคุณผิดปกติตรงไหน?”
มีสามเหตุผลตรงไปตรงมาที่ทำให้เราคิดราคานี้ได้:
1. เราไม่ run browser
DocRaptor amortise Prince infrastructure ระหว่าง customers ส่วน gPdf amortise Cloudflare Worker หนึ่งตัว ซึ่งมี cost ประมาณ $0.50/million requests บน Workers Bundled ด้วย JSON-shaped input renderer ของเราใช้ประมาณ 1.5 ms CPU per render ใส่ margin 50% แล้วก็ยังอยู่ใน range cents-per-thousand-renders Arithmetic คือ price
2. เราไม่ run 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” ส่วนใหญ่ตั้งงบไว้ออกไป และ surface นั้นเองที่ justify price ของพวกเขา
3. Model self-select workloads ที่เราจะขาดทุนออกเอง
ถ้า document ของคุณต้องการ HTML-to-PDF จริง ๆ เช่น 60-page legal contract หรือ complex CSS-Grid report คุณจะ bounce จาก JSON model ในชั่วโมงแรกแล้วไป DocRaptor เอง เราไม่ต้องตั้ง price กันความเสี่ยงสำหรับ workloads เหล่านั้น เพราะมัน self-route เราต้อง price เฉพาะ long-but-narrow tail ของ “structured-data-to-document” workloads ซึ่ง per-render cost เล็กจริง ๆ
รวมกันแล้ว $5/100K ไม่ใช่ loss leader แต่คือ actual cost-of-goods-sold plus margin เรารักษาราคานี้ได้ เพราะ underlying compute ถูกขนาดนั้นจริง ๆ เมื่อคุณไม่ได้ ship browser
เมื่อ DocRaptor เป็น choice ที่ถูกต้อง
เราไม่พยายามเขียน comparison ที่เข้าข้างตัวเอง Cases ที่ DocRaptor ชนะจริง ๆ:
- Input ของคุณคือ HTML ที่คุณ control ไม่ครบถ้วน เช่น user-generated reports, third-party templates, Markdown จาก CMS ที่ render เป็น HTML คุณไม่ควรเขียน JSON mapper สำหรับ arbitrary input
- คุณต้องการ CSS Paged Media features ที่ Prince support เช่น running headers/footers per chapter, complex footnote reflow, named-page selectors, generated tables of contents, indexes gPdf มี structured equivalents สำหรับ common subset แต่ถ้าคุณใช้
@page :leftselectors เป็นหลัก Prince คือเพื่อนของคุณ - คุณมี content team ที่เขียน HTML/CSS ไม่ใช่ JSON อย่าบังคับ JSON authoring workflow กับ non-engineering team พวกเขาจะไม่ชอบ
- Async + callbacks + document storage as a service DocRaptor store generated PDFs และให้ signed URLs สำหรับ delivery ส่วน gPdf strict stateless code ของคุณต้อง store result เอง
ถ้าคุณอยู่ใน bucket เหล่านี้ อยู่กับ DocRaptor นั่นคือ tool ที่ถูกต้อง
เมื่อ gPdf เป็น choice ที่ถูกต้อง
ภาพกลับกัน:
- 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 สูงกว่าไม่กี่พัน renders/month
- คุณต้องการ barcodes เช่น GS1-128, QR, Data Matrix, PDF417, Aztec, MaxiCode ที่ sub-millimetre precision Prince technically support SVG barcodes แต่ทำให้ได้ 0.1 mm overall length precision ผ่าน HTML/CSS ไม่ trivial
- คุณต้องการ PDF/A (1b/2b/3b/4) หรือ Factur-X / ZUGFeRD attachments สำหรับ compliance
- คุณไม่อยาก run JSON-to-HTML-to-PDF pipeline เมื่อ run JSON-to-PDF pipeline ได้
Migration เป็นเรื่อง mechanical ไม่ใช่ strategic
Worry ที่พบบ่อยคือ “Switching แปลว่าต้อง rewrite templates ทั้งหมด” ส่วนใหญ่ไม่ใช่ Most HTML-to-PDF templates คือ 20% layout ซึ่งกลายเป็น JSON structure ครั้งเดียว และ 80% data interpolation ซึ่งเหมือนเดิมไม่ว่า renderer รับอะไร
Practical path:
- เลือก document type เดียว เพื่อ migrate เริ่มจาก highest-volume one เพราะ saving ใหญ่ที่สุดและ blast radius เล็กที่สุด
- เอา data interface ของ HTML template คือ variables ที่มัน interpolate แล้วเขียน function เล็กชื่อ
mapToDocumentRequest(data) - Iterate ใน Playground จน output match
- A/B ใน production: route 5% traffic ไป gPdf สอง weeks Diff PDFs และ compare bills
- Roll forward หรือ roll back ตาม data ไม่ใช่ vibes
เราเคยเห็น teams ทำสิ่งนี้ใน sprint เดียวและลด PDF bill ได้ 90% ในเดือนถัดไป เราก็เคยเห็น teams รู้ว่า workload ของตัวเองเป็น HTML-to-PDF case จริง ๆ แล้วอยู่กับ DocRaptor ต่อ ซึ่งก็เป็น decision ที่ถูกต้อง
TL;DR
| DocRaptor | gPdf | |
|---|---|---|
| Best at | HTML → PDF สำหรับ arbitrary content | JSON → PDF สำหรับ structured documents |
| 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 ของคุณคือ structured data ที่แต่งเป็น HTML เพื่อ renderer คุณกำลังจ่ายให้ translation step ที่ไม่จำเป็น ลอง Playground: describe invoice หนึ่งใบเป็น JSON, render ใน browser ต่ำกว่า 5 ms แล้วดูว่า gap ตรงกับความรู้สึกของคุณหรือไม่