DocRaptor to kompetentny produkt. Owija Prince — referencyjny silnik HTML-do-PDF — w hostowane REST API, z retry, asynchronicznymi job-ami i przyzwoitą dokumentacją. Istnieje od ponad dekady i dla wielu zespołów to oczywisty wybór «nie chcę sam zarządzać Prince».
My jesteśmy narzędziem o innym kształcie. gPdf w ogóle nie przyjmuje HTML; bierze strukturyzowany JSON i renderuje bezpośrednio na edge Cloudflare. Różnica cen listowych przy 100K stron/miesiąc: $5/miesiąc (gPdf Basic) vs $89/miesiąc (DocRaptor Basic) — około 18×. Ta różnica nie jest promocją otwarcia. Jest strukturalna. Ten post wyjaśnia dlaczego struktura produkuje tę cenę i gdzie każde narzędzie naprawdę pasuje.
Dwie architektury obok siebie
| Warstwa | DocRaptor (HTML → PDF) | gPdf (JSON → PDF) |
|---|---|---|
| Wejście | HTML + CSS (z rozszerzeniami Prince paged-media) | JSON DocumentRequest |
| Renderer | Prince (skompilowany silnik C++) | Własny silnik Rust, skompilowany do WebAssembly |
| Hosting | Scentralizowane serwery DocRaptor (datacenter US) | Cloudflare Workers, każde colo CF (300+ miast) |
| Cold start | Pool workerów po stronie serwera | Boot V8 isolate, jednocyfrowe ms |
| Compute na render | Pass layoutu po HTML/CSS, potem Prince paginuje | Bezpośrednie składanie, bez passu interpretacji layoutu |
| p50 na render | ~250–800 ms wall-clock (sieć + render) | ~3–8 ms (sieć + render) |
| Determinizm wyjścia | Wysoki (Prince jest dojrzały) | Bajt-identyczny (ten sam JSON → te same bajty) |
Jeśli czytasz te dwie kolumny jako «ogólna drukarka HTML» vs «renderer dokumentów zbudowany do celu», już zrozumiałeś decyzję architektoniczną. Wszystko inne (latencja, koszt, nawet listy funkcji) jest pochodną tej jednej decyzji.
Podatek Prince
Prince jest dobry. Robi też pracę, której większość workflow faktura/paragon/etykieta nie potrzebuje: implementuje CSS Paged Media — reguły łamania stron, biegnące nagłówki, przypisy, odniesienia, generowaną treść — dla dowolnego HTML, który użytkownik może wrzucić.
Ta uniwersalność ma koszt runtime. Aby paginować dowolny HTML, silnik musi:
- Sparsować i zwalidować HTML
- Rozwiązać kaskadę CSS (potencjalnie z własnymi rozszerzeniami Prince)
- Zbudować drzewo renderowania
- Wykonać layout multi-pass (zwłaszcza dla tabel rozciągających się przez strony lub kolumn balansujących)
- Rozwiązać odniesienia między stronami
- Wyemitować obiekty PDF
Większość tych passów to koszt akceptowania HTML jako wejścia. Jeśli twoje wejście to już strukturyzowane dane (a prawie zawsze tak jest — twoja faktura istnieje jako obiekt JSON zanim opakujesz ją w HTML), płacisz za te passy w compute i latencji przy każdym renderze, a nie dodają wartości do wyjścia.
gPdf całkowicie pomija krok interpretacji layoutu. JSON DocumentRequest już strukturalnie specyfikuje layout strony — { pages: [{ size, elements: [...] }] }. Renderer składa elementy, paginuje tabele/listy deterministycznie i emituje PDF. Bez kaskady CSS do rozwiązania, bez layoutu floatów do obliczenia, bez passu rozwiązywania odniesień.
Wynik: ta sama jednostronicowa faktura, która zajmuje ~300 ms na DocRaptor, zajmuje ~3 ms na gPdf. Nie jesteśmy szybsi, bo napisaliśmy szybszego Prince — jesteśmy szybsi, bo nie robimy większości tego, co robi Prince.
«Za tanio, żeby być prawdziwym» to prawdziwy zarzut przy zakupie
Zaadresujmy to bezpośrednio, bo wyłazi w każdej rozmowie sprzedażowej B2B.
«$5/miesiąc za 100K renderów. DocRaptor to $89. Anvil to $0,10/PDF (czyli $10.000 przy tym samym wolumenie). Co z wami nie tak?»
Trzy uczciwe powody, dla których możemy tyle pobierać:
1. Nie uruchamiamy przeglądarki
DocRaptor amortyzuje infrastrukturę Prince między klientami. gPdf amortyzuje jeden Cloudflare Worker, który kosztuje około $0,50/milion request na Workers Bundled. Z wejściem w formie JSON, nasz renderer zajmuje około 1,5 ms CPU na render. Dodaj 50 % marży i nadal jesteś w przedziale centów-na-tysiąc-renderów. Arytmetyka to cena.
2. Nie uruchamiamy control plane
Brak asynchronicznych jobów, brak callbacków, brak kolejki retry, brak storage dokumentów, brak UI linka podglądu, brak multi-tenant database. Każdy render to jeden round-trip do bezstanowej funkcji i z powrotem. To usuwa całą powierzchnię ops, którą większość firm «PDF API» budżetuje — która jest też powierzchnią uzasadniającą ich cenę.
3. Model auto-selekcjonuje workloady, na których byśmy stracili
Jeśli twój dokument naprawdę potrzebuje HTML-do-PDF (60-stronicowa umowa prawna, złożony raport CSS-Grid), odbijesz się od modelu JSON w pierwszej godzinie i pójdziesz do DocRaptor i tak. Nie musimy bronić cen dla tych workloadów, bo same się rozróżniają. Musimy tylko cenić długi ale wąski ogon workloadów «dane-strukturyzowane-do-dokumentu», gdzie koszt na render jest naprawdę mikroskopijny.
Razem: $5/100K to nie loss-leader, to rzeczywisty koszt sprzedaży plus marża. Możemy utrzymywać tę cenę na czas nieokreślony, bo bazowy compute jest tak tani, gdy nie wysyłasz przeglądarki.
Gdzie DocRaptor jest właściwym wyborem
Staramy się nie pisać własno-interesownych porównań. Przypadki, w których DocRaptor naprawdę wygrywa:
- Twoje wejście to HTML, którego nie kontrolujesz w pełni. Raporty generowane przez użytkowników, szablony stron trzecich, Markdown-z-CMS-renderowany-do-HTML. Nie chcesz pisać mappera JSON dla dowolnych wejść.
- Potrzebujesz funkcji CSS Paged Media wspieranych przez Prince. Biegnące nagłówki/stopki na rozdział, złożony reflow przypisów, nazwane selektory stron, generowane spisy treści, indeksy. gPdf ma strukturalne odpowiedniki dla wspólnego podzbioru, ale jeśli żyjesz w selektorach
@page :left, Prince jest twoim przyjacielem. - Masz zespół content-owy piszący HTML/CSS, nie JSON. Nie narzucaj workflow autorskiego JSON nieinżynierskiemu zespołowi. Znienawidzą cię.
- Async + callbacki + storage dokumentów jako usługa. DocRaptor przechowuje wygenerowane PDFy i daje ci podpisane URLe do dostawy. gPdf jest ściśle bezstanowy — twój kod przechowuje wynik.
Jeśli jesteś w którymś z tych worków, zostań na DocRaptor. To właściwe narzędzie.
Gdzie gPdf jest właściwym wyborem
Lustrzane odbicie:
- Twoje wejścia to już strukturyzowane dane (wiersze bazy danych, payloady JSON API, wiadomości kolejki).
- Latencja ma znaczenie — interaktywne flow checkout, druk etykiet w czasie rzeczywistym, generowanie wyciągów na żądanie.
- Zależy ci na bajt-identycznej powtarzalności dla testów / audit trail / przechowywania e-faktur.
- Jesteś wrażliwy na koszty przy każdym wolumenie powyżej kilku tysięcy renderów/miesiąc.
- Potrzebujesz kodów kreskowych (GS1-128, QR, Data Matrix, PDF417, Aztec, MaxiCode) z sub-milimetrową precyzją.
- Potrzebujesz PDF/A (1b/2b/3b/4) lub załączników Factur-X / ZUGFeRD dla compliance — szczególnie istotne dla polskiego mandatu KSeF od lipca 2024 i mandatów EU rolujących się 2024-2027.
- Wolałbyś nie uruchamiać pipeline’u JSON-do-HTML-do-PDF, kiedy możesz uruchomić pipeline JSON-do-PDF.
Konkretna uwaga dla polskich zespołów na KSeF
Jeśli twój kontekst to polski mandat KSeF (Krajowy System e-Faktur) — obowiązkowy dla B2B od lipca 2024 — gPdf produkuje wymagany format Factur-X w pojedynczym wywołaniu API. Choć KSeF używa swojego własnego formatu XML (FA(2)), wiele systemów ERP integruje go równolegle z formatem EN 16931 dla interoperacyjności EU:
curl -X POST https://gpdf.com/api/v1/e-invoice/render \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data '{
"document": { "pages": [{ "size": "a4", "elements": [...] }] },
"einvoice": {
"format": "factur-x",
"profile": "BASIC",
"xml": "<rsm:CrossIndustryInvoice>...</rsm:CrossIndustryInvoice>"
}
}' \
--output faktura.pdf
Bez post-passu Ghostscript, bez drugiego narzędzia do dołączenia XML, bez loterii walidacji między krokami. Bajty wyjścia są bajt-identyczne między wersjami silnika, więc twój hash przechowywania dla 5-letniego obowiązku skarbowego może pozostać stabilny.
Migracja jest mechaniczna, nie strategiczna
Powszechna obawa: «Zmiana oznacza przepisanie wszystkich naszych szablonów». Zazwyczaj nie. Większość szablonów HTML-do-PDF to 20 % layoutu (który raz staje się strukturą JSON) i 80 % interpolacji danych (która jest dokładnie taka sama niezależnie od tego, co bierze renderer).
Praktyczna ścieżka:
- Wybierz jeden typ dokumentu do migracji. Zacznij od najwyższego wolumenu — największe oszczędności, najmniejszy promień rażenia.
- Weź interfejs danych szablonu HTML (zmienne, które interpoluje) i napisz małą funkcję
mapToDocumentRequest(data). - Iteruj wobec Playground, aż wyjście się zgadza.
- A/B w produkcji: skieruj 5 % ruchu do gPdf przez dwa tygodnie. Diff PDFy. Porównaj rachunki.
- Idź naprzód lub się wycofaj na podstawie danych, nie wibracji.
TL;DR
| DocRaptor | gPdf | |
|---|---|---|
| Najlepszy do | HTML → PDF dla dowolnej treści | JSON → PDF dla strukturyzowanych dokumentów |
| Cena (100K stron/miesiąc) | $89 | $5 |
| Render p50 | 250–800 ms | 3–8 ms |
| Edge-deployed | ❌ scentralizowane | ✅ 300+ colos Cloudflare |
| Async + storage | ✅ wliczone | ❌ stateless by design |
| PDF/A + Factur-X / ZUGFeRD | ⚠️ przez rozszerzenia Prince | ✅ wbudowane |
Jeśli twoje dokumenty to strukturyzowane dane przebrane za HTML dla renderera, płacisz za krok tłumaczenia, który nie musi istnieć. Wypróbuj Playground — opisz jedną ze swoich faktur w JSON, wyrenderuj ją w przeglądarce w mniej niż 5 ms, zobacz, czy różnica zgadza się z twoją intuicją.