Blog

gPdf vs DocRaptor: Warum Edge-Rendering HTML-zu-PDF schlägt

DocRaptor verwendet Prince, um HTML auf einem gehosteten Backend in PDF umzuwandeln. gPdf rendert strukturiertes JSON direkt am Cloudflare Edge. Die Preislücke beträgt 18×. Hier ist, warum das kein Lockangebot ist.

DocRaptor ist ein kompetentes Produkt. Es verpackt Prince — die Goldstandard-HTML-zu-PDF-Engine — in eine gehostete REST-API mit Retries, asynchronen Jobs und ordentlicher Dokumentation. Es existiert seit über zehn Jahren, und für viele Teams ist es die offensichtliche „Ich will Prince nicht selbst betreiben”-Wahl.

Wir sind ein Werkzeug anderer Form. gPdf nimmt überhaupt kein HTML; es nimmt strukturiertes JSON und rendert direkt am Cloudflare Edge zu PDF. Die Listenpreis-Lücke bei 100K Seiten/Monat: 5 $/Monat (gPdf Basic) vs. 89 $/Monat (DocRaptor Basic) — etwa 18×. Diese Lücke ist kein Eröffnungsangebot. Sie ist strukturell. Dieser Beitrag erklärt, warum die Struktur diesen Preis erzeugt, und wo jedes Werkzeug tatsächlich passt.

Die zwei Architekturen, nebeneinander

SchichtDocRaptor (HTML → PDF)gPdf (JSON → PDF)
EingabeHTML + CSS (mit Prince Paged-Media-Erweiterungen)DocumentRequest-JSON
RendererPrince (kompilierte C++-Engine)Eigene Rust-Engine, kompiliert zu WebAssembly
HostingZentralisierte DocRaptor-Server (US-Datacentre)Cloudflare Workers, jedes CF-Colo (300+ Städte)
Cold StartServer-seitiger Worker-PoolV8-Isolate-Boot, einstellige ms
Compute pro RenderLayout-Pass über HTML/CSS, dann Prince paginiertDirekter Satz, kein Layout-Interpretations-Pass
p50 pro Render~250–800 ms Wandzeit (Netzwerk + Render)~3–8 ms (Netzwerk + Render)
Output-DeterminismusHoch (Prince ist reif)Byte-identisch (gleiches JSON → gleiche Bytes)

Wenn du diese zwei Spalten als „allgemeiner HTML-Drucker” vs. „zweckgebauter Dokumenten-Renderer” liest, hast du die Architektur-Entscheidung bereits verstanden. Alles andere (Latenz, Kosten, sogar die Feature-Listen) ist downstream dieser einen Wahl.

Die Prince-Steuer

Prince ist gut. Es macht aber auch einen Job, den die meisten Rechnungs-/Quittungs-/Etiketten-Workflows nicht brauchen: CSS Paged Media — Seitenumbruch-Regeln, Running Headers, Fußnoten, Querverweise, generierte Inhalte — für beliebiges HTML implementieren, das der Nutzer reinwerfen könnte.

Diese Allgemeingültigkeit hat Laufzeitkosten. Um beliebiges HTML zu paginieren, muss die Engine:

  1. HTML parsen und validieren
  2. CSS-Kaskade auflösen (möglicherweise mit Prince-eigenen Erweiterungen)
  3. Render-Tree bauen
  4. Multi-Pass-Layout fahren (besonders für Tabellen, die über Seiten gehen, oder Spalten, die balancieren)
  5. Querverweise über Seiten hinweg auflösen
  6. PDF-Objekte ausgeben

Die meisten dieser Pässe sind die Kosten dafür, HTML als Eingabe zu akzeptieren. Wenn deine Eingabe bereits strukturierte Daten ist (was sie fast immer ist — deine Rechnung existiert als JSON-Objekt, bevor du sie in HTML wickelst), zahlst du diese Pässe in Compute und Latenz bei jedem Render, und sie fügen dem Output keinen Wert hinzu.

gPdf überspringt den Layout-Interpretations-Schritt komplett. Der JSON-DocumentRequest spezifiziert das Seitenlayout bereits strukturell — { pages: [{ size, elements: [...] }] }. Der Renderer setzt die Elemente, paginiert Tabellen/Listen deterministisch und gibt PDF aus. Keine CSS-Kaskade aufzulösen, kein Float-Layout zu berechnen, kein Querverweis-Auflösungs-Pass.

Ergebnis: Die einseitige Rechnung, die auf DocRaptor ~300 ms braucht, braucht auf gPdf ~3 ms. Wir sind nicht schneller, weil wir ein schnelleres Prince geschrieben haben — wir sind schneller, weil wir das Meiste, was Prince tut, nicht tun.

„Zu billig, um wahr zu sein” ist ein echter Beschaffungs-Einwand

Adressieren wir das direkt, weil es in jedem B2B-Verkaufsgespräch hochkommt.

„5 $/Monat für 100K Renderings. DocRaptor ist 89 $. Anvil ist 0,10 $/PDF (also 10.000 $ für dasselbe Volumen). Was stimmt mit euch nicht?”

Drei ehrliche Gründe, warum wir das berechnen können:

1. Wir betreiben keinen Browser

DocRaptor amortisiert Prince-Infrastruktur über Kunden. gPdf amortisiert einen Cloudflare Worker, der etwa 0,50 $/Million Requests auf Workers Bundled kostet. Mit JSON-förmiger Eingabe braucht unser Renderer etwa 1,5 ms CPU pro Render. Lege 50 % Marge oben drauf und du bist immer noch im Cent-pro-Tausend-Renderings-Bereich. Die Arithmetik ist der Preis.

2. Wir betreiben keine Control Plane

Es gibt keine asynchronen Jobs, keine Callbacks, keine Retry-Queue, keine Dokumentenspeicherung, keine Vorschau-Link-UI, keine Multi-Tenant-Datenbank. Jedes Render ist ein einzelner Round-Trip zu einer zustandslosen Funktion und zurück. Das entfernt die gesamte Ops-Oberfläche, die die meisten „PDF-API”-Firmen budgetieren — was auch die Oberfläche ist, die ihren Preis rechtfertigt.

3. Das Modell selektiert die Workloads heraus, bei denen wir Geld verlieren würden

Wenn dein Dokument echt HTML-zu-PDF braucht (60-seitiger Rechtsvertrag, komplexer CSS-Grid-Report), wirst du in der ersten Stunde vom JSON-Modell abprallen und sowieso zu DocRaptor gehen. Wir müssen für diese Workloads nicht defensiv preisen, weil sie sich selbst routen. Wir müssen nur für den langen, schmalen Schwanz von „Strukturierte-Daten-zu-Dokument”-Workloads preisen, wo die Kosten pro Render echt winzig sind.

Zusammen: 5 $/100K ist kein Verlust-Lockangebot, es ist die tatsächlichen Selbstkosten plus Marge. Wir können es unbegrenzt dort halten, weil die zugrunde liegende Compute wirklich so billig ist, wenn man keinen Browser ausliefert.

Wo DocRaptor die richtige Wahl ist

Wir versuchen, keine eigennützigen Vergleiche zu schreiben. Die Fälle, in denen DocRaptor wirklich gewinnt:

  • Deine Eingabe ist HTML, das du nicht vollständig kontrollierst. Nutzer-generierte Berichte, Drittanbieter-Templates, Markdown-aus-CMS-zu-HTML. Du willst keinen JSON-Mapper für beliebige Eingaben schreiben.
  • Du brauchst CSS-Paged-Media-Features, die Prince unterstützt. Running Headers/Footers pro Kapitel, komplexe Fußnoten-Reflow, benannte Page-Selektoren, generierte Inhaltsverzeichnisse, Indizes. gPdf hat strukturierte Äquivalente für die gemeinsame Teilmenge, aber wenn du in @page :left-Selektoren lebst, ist Prince dein Freund.
  • Du hast ein Content-Team, das HTML/CSS schreibt, nicht JSON. Erlege keinem Nicht-Engineering-Team einen JSON-Authoring-Workflow auf. Sie werden dich hassen.
  • Async + Callbacks + Document Storage as a Service. DocRaptor speichert generierte PDFs und gibt dir signierte URLs zur Auslieferung. gPdf ist strikt zustandslos — dein Code speichert das Ergebnis.

Wenn du in einem dieser Eimer bist, bleib bei DocRaptor. Es ist das richtige Werkzeug.

Wo gPdf die richtige Wahl ist

Das Spiegelbild:

  • Deine Eingaben sind bereits strukturierte Daten (Datenbankzeilen, JSON-API-Payloads, Queue-Nachrichten).
  • Latenz zählt — interaktive Checkout-Flows, Echtzeit-Etikettendruck, On-Demand-Kontoauszug-Generierung.
  • Dir liegt an byte-identischer Reproduzierbarkeit für Tests / Audit-Trails / E-Rechnung-Aufbewahrung.
  • Du bist kostensensitiv bei jedem Volumen über ein paar Tausend Renderings/Monat.
  • Du brauchst Barcodes (GS1-128, QR, Data Matrix, PDF417, Aztec, MaxiCode) mit Sub-Millimeter-Präzision.
  • Du brauchst PDF/A (1b/2b/3b/4) oder Factur-X / ZUGFeRD-Anhänge für Compliance — speziell relevant für das deutsche E-Rechnungs-Mandat seit 2025-01 und das anstehende französische Mandat ab September 2026.
  • Du würdest lieber keine JSON-zu-HTML-zu-PDF-Pipeline fahren, wenn du eine JSON-zu-PDF-Pipeline fahren kannst.

ZUGFeRD-spezifischer Hinweis für deutsche Teams

Wenn dein Kontext das deutsche B2B-E-Rechnungs-Mandat ist (gilt für Rechnungsempfang seit 2025-01-01, für Ausstellung ab 2027), liefert gPdf direkt das ZUGFeRD-Format als einzelnen API-Aufruf — PDF/A-3 + eingebettetes EN-16931-XML in einem Schritt:

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": "zugferd",
      "profile": "BASIC",
      "xml": "<rsm:CrossIndustryInvoice>...</rsm:CrossIndustryInvoice>"
    }
  }' \
  --output rechnung.pdf

Kein Ghostscript-Post-Pass, kein zweites Tool zum Anhängen der XML, keine Validierungs-Lottery zwischen Schritten. Die Ausgabe-Bytes sind byte-identisch über Engine-Versionen hinweg, also kann dein Aufbewahrungs-Hash für die 10-jährige steuerliche Pflicht stabil bleiben.

Migration ist mechanisch, nicht strategisch

Eine häufige Sorge: „Wechseln bedeutet, alle unsere Templates neu zu schreiben.” Tut es meistens nicht. Die meisten HTML-zu-PDF-Templates sind 20 % Layout (was einmal zu JSON-Struktur wird) und 80 % Daten-Interpolation (was unabhängig vom Renderer dasselbe ist).

Praktischer Pfad:

  1. Wähle einen Dokumenttyp zur Migration. Beginne mit dem volumenstärksten — größte Einsparung, kleinster Blast Radius.
  2. Nimm das Daten-Interface des HTML-Templates (die Variablen, die es interpoliert) und schreibe eine kleine mapToDocumentRequest(data)-Funktion.
  3. Iteriere gegen den Playground, bis die Ausgabe passt.
  4. A/B in Produktion: route 5 % des Traffics für zwei Wochen zu gPdf. Diff die PDFs. Vergleiche Rechnungen.
  5. Roll vorwärts oder zurück basierend auf Daten, nicht Bauchgefühl.

Wir haben Teams diesen Wechsel in einem einzigen Sprint machen sehen und 90 % ihrer PDF-Rechnung im nächsten Monat einstecken. Wir haben auch Teams gesehen, die realisiert haben, dass ihr Workload tatsächlich der HTML-zu-PDF-Fall war, und auf DocRaptor geblieben — mit unserem Segen.

TL;DR

DocRaptorgPdf
Am besten beiHTML → PDF für beliebigen InhaltJSON → PDF für strukturierte Dokumente
Preis (100K Seiten/Monat)89 $5 $
p50 Render250–800 ms3–8 ms
Edge-bereitgestellt❌ zentralisiert✅ 300+ Cloudflare-Colos
Async + Storage✅ enthalten❌ designbedingt zustandslos
PDF/A + Factur-X / ZUGFeRD⚠️ via Prince-Erweiterungen✅ eingebaut

Wenn deine Dokumente strukturierte Daten sind, die als HTML für einen Renderer verkleidet sind, zahlst du für einen Übersetzungs-Schritt, der nicht existieren muss. Probiere den Playground — beschreibe eine deiner Rechnungen in JSON, render sie in deinem Browser in unter 5 ms, schau, ob die Lücke deinem Bauchgefühl entspricht.