Blog

gPdf vs DocRaptor: perché il rendering al edge batte l'HTML-to-PDF

DocRaptor usa Prince per convertire HTML in PDF su backend hosted. gPdf renderizza JSON strutturato direttamente al edge Cloudflare. Il gap di prezzo è 18×. Ecco perché non è un'esca.

DocRaptor è un prodotto competente. Avvolge Prince — il motore HTML-to-PDF di riferimento — in un’API REST hosted, con retry, job asincroni e documentazione decente. È in giro da oltre dieci anni e per molti team è la scelta ovvia «non voglio gestire Prince da solo».

Noi siamo uno strumento di forma diversa. gPdf non accetta HTML affatto; prende JSON strutturato e renderizza direttamente al edge Cloudflare. Il gap di prezzo di listino a 100K pagine/mese: $5/mese (gPdf Basic) vs $89/mese (DocRaptor Basic) — circa 18×. Quel gap non è un’offerta lancio. È strutturale. Questo post spiega perché la struttura produce quel prezzo, e dove ogni strumento si adatta veramente.

Le due architetture, fianco a fianco

StratoDocRaptor (HTML → PDF)gPdf (JSON → PDF)
InputHTML + CSS (con estensioni Prince paged-media)DocumentRequest JSON
RendererPrince (engine C++ compilato)Engine Rust proprietario, compilato in WebAssembly
HostingServer DocRaptor centralizzati (datacenter US)Cloudflare Workers, ogni colo CF (300+ città)
Cold startPool di worker server-sideBoot di isolate V8, ms a una cifra
Compute per renderPass di layout su HTML/CSS, poi Prince paginaComposizione diretta, nessun pass di interpretazione layout
p50 per render~250–800 ms wall-clock (rete + render)~3–8 ms (rete + render)
Determinismo outputAlto (Prince è maturo)Byte-identico (stesso JSON → stessi byte)

Se leggi queste due colonne come «stampante HTML generica» vs «renderer di documenti progettato apposta», hai già capito la decisione architettonica. Tutto il resto (latenza, costi, anche le liste feature) è a valle di questa singola scelta.

La tassa Prince

Prince è buono. Sta anche facendo un lavoro che la maggior parte dei workflow fattura/ricevuta/etichetta non necessitano: implementare CSS Paged Media — regole di interruzione di pagina, header running, note a piè di pagina, riferimenti incrociati, contenuto generato — per HTML arbitrario che l’utente potrebbe lanciargli.

Quella generalità ha un costo runtime. Per paginare HTML arbitrario, l’engine deve:

  1. Parsare e validare l’HTML
  2. Risolvere la cascade CSS (eventualmente con estensioni proprie di Prince)
  3. Costruire l’albero di render
  4. Eseguire layout multi-pass (specialmente per tabelle che attraversano pagine, o colonne che si bilanciano)
  5. Risolvere riferimenti incrociati tra pagine
  6. Emettere oggetti PDF

La maggior parte di quei pass sono il costo di accettare HTML come input. Se il tuo input è già dati strutturati (cosa che è quasi sempre — la tua fattura esiste come oggetto JSON prima che tu la avvolga in HTML), stai pagando quei pass in compute e latenza ad ogni render, e non aggiungono valore all’output.

gPdf salta del tutto lo step di interpretazione layout. Il DocumentRequest JSON specifica già il layout della pagina strutturalmente — { pages: [{ size, elements: [...] }] }. Il renderer compone gli elementi, pagina tabelle/liste in modo deterministico ed emette PDF. Niente cascade CSS da risolvere, niente layout di float da computare, niente pass di risoluzione riferimenti incrociati.

Risultato: la stessa fattura di una pagina che impiega ~300 ms su DocRaptor impiega ~3 ms su gPdf. Non siamo più veloci perché abbiamo scritto un Prince più veloce — siamo più veloci perché non facciamo la maggior parte di ciò che fa Prince.

«Troppo economico per essere vero» è un’obiezione di procurement reale

Affrontiamola direttamente perché viene fuori in ogni call commerciale B2B.

«$5/mese per 100K render. DocRaptor è $89. Anvil è $0,10/PDF (quindi $10.000 allo stesso volume). Cosa c’è che non va in voi?»

Tre ragioni oneste per cui possiamo addebitare questo:

1. Non gestiamo un browser

DocRaptor ammortizza l’infrastruttura Prince tra clienti. gPdf ammortizza un Cloudflare Worker, che costa circa $0,50/milione di request su Workers Bundled. Con input in forma JSON, il nostro renderer impiega circa 1,5 ms di CPU per render. Aggiungi un margine del 50 % e sei ancora nell’intervallo dei centesimi-per-mille-render. L’aritmetica è il prezzo.

2. Non gestiamo un control plane

Niente job asincroni, niente callback, niente coda di retry, niente storage di documenti, niente UI di link di anteprima, niente database multi-tenant. Ogni render è un singolo round-trip a una funzione stateless e ritorno. Questo rimuove l’intera superficie ops che la maggior parte delle aziende «PDF API» mette a budget — che è anche la superficie che giustifica il loro prezzo.

3. Il modello si auto-seleziona fuori dai workload su cui perderemmo soldi

Se il tuo documento ha veramente bisogno di HTML-to-PDF (contratto legale 60 pagine, report CSS-Grid complesso), rimbalzerai dal modello JSON nella prima ora e andrai comunque su DocRaptor. Non dobbiamo prezzare difensivamente per quei workload perché si auto-instradano. Dobbiamo solo prezzare per la coda lunga ma stretta dei workload «dati-strutturati-a-documento», dove il costo per render è genuinamente minuscolo.

Insieme: $5/100K non è una loss-leader, è il vero costo del venduto più margine. Possiamo mantenerlo lì indefinitamente perché il compute sottostante è veramente così economico quando non spedisci un browser.

Dove DocRaptor è la scelta giusta

Cerchiamo di non scrivere confronti autointeressati. I casi dove DocRaptor vince genuinamente:

  • Il tuo input è HTML che non controlli completamente. Report generati da utenti, template di terze parti, Markdown-da-CMS-renderizzato-a-HTML. Non vuoi scrivere un mapper JSON per input arbitrari.
  • Hai bisogno di feature CSS Paged Media supportate da Prince. Header/footer running per capitolo, reflow complesso di note a piè di pagina, selettori di pagina nominati, indici e tavole dei contenuti generate. gPdf ha equivalenti strutturati per il sottoinsieme comune, ma se vivi nei selettori @page :left, Prince è tuo amico.
  • Hai un team di contenuti che scrive HTML/CSS, non JSON. Non imporre un workflow di authoring JSON a un team non-engineering. Ti odieranno.
  • Async + callback + storage documenti come servizio. DocRaptor archivia i PDF generati e ti dà URL firmati per la consegna. gPdf è strettamente stateless — il tuo codice archivia il risultato.

Se sei in uno di questi secchi, rimani su DocRaptor. È lo strumento giusto.

Dove gPdf è la scelta giusta

L’immagine speculare:

  • I tuoi input sono già dati strutturati (righe di database, payload API JSON, messaggi di coda).
  • La latenza conta — flussi checkout interattivi, stampa etichette in tempo reale, generazione estratti conto on-demand.
  • Ti importa la riproducibilità byte-identica per test / audit trail / conservazione fatture elettroniche.
  • Sei sensibile ai costi a qualsiasi volume sopra qualche migliaio di render/mese.
  • Ti servono codici a barre (GS1-128, QR, Data Matrix, PDF417, Aztec, MaxiCode) con precisione sub-millimetrica.
  • Ti serve PDF/A (1b/2b/3b/4) o allegati Factur-X / ZUGFeRD per compliance — particolarmente rilevante per il mandato italiano FatturaPA in vigore dal 2019 e i mandati EU in roll-out 2024-2027.
  • Preferiresti non gestire una pipeline JSON-a-HTML-a-PDF quando puoi gestire una pipeline JSON-a-PDF.

Nota specifica per team italiani su FatturaPA

Se il tuo contesto è il mandato italiano FatturaPA (B2B obbligatorio dal 2019 via SDI), gPdf produce il formato Factur-X richiesto in una singola chiamata API — PDF/A-3 + XML EN-16931 integrato in un passo:

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 fattura.pdf

Niente post-pass Ghostscript, niente secondo strumento per allegare l’XML, niente lotteria di validazione tra step. I byte di output sono byte-identici tra versioni dell’engine, quindi il tuo hash di conservazione per l’obbligo fiscale di 10 anni può rimanere stabile.

La migrazione è meccanica, non strategica

Una preoccupazione comune: «Cambiare significa riscrivere tutti i nostri template». Generalmente no. La maggior parte dei template HTML-to-PDF sono 20 % layout (che diventa struttura JSON una volta) e 80 % interpolazione di dati (che è esattamente la stessa indipendentemente da cosa accetta il renderer).

Percorso pratico:

  1. Scegli un tipo di documento da migrare. Inizia da quello con maggior volume — maggior risparmio, minor blast radius.
  2. Prendi l’interfaccia dati del template HTML (le variabili che interpola) e scrivi una piccola funzione mapToDocumentRequest(data).
  3. Itera contro il Playground finché l’output combacia.
  4. A/B in produzione: instrada 5 % del traffico a gPdf per due settimane. Diff i PDF. Confronta le fatture.
  5. Vai avanti o indietro in base ai dati, non alle vibrazioni.

TL;DR

DocRaptorgPdf
Migliore perHTML → PDF per contenuto arbitrarioJSON → PDF per documenti strutturati
Prezzo (100K pagine/mese)$89$5
Render p50250–800 ms3–8 ms
Edge-deployed❌ centralizzato✅ 300+ colos Cloudflare
Async + storage✅ incluso❌ stateless by design
PDF/A + Factur-X / ZUGFeRD⚠️ via estensioni Prince✅ integrato

Se i tuoi documenti sono dati strutturati travestiti da HTML per un renderer, stai pagando per uno step di traduzione che non deve esistere. Prova il Playground — descrivi una delle tue fatture in JSON, renderizzala nel tuo browser in meno di 5 ms, vedi se il gap combacia con la tua intuizione.