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
| Strato | DocRaptor (HTML → PDF) | gPdf (JSON → PDF) |
|---|---|---|
| Input | HTML + CSS (con estensioni Prince paged-media) | DocumentRequest JSON |
| Renderer | Prince (engine C++ compilato) | Engine Rust proprietario, compilato in WebAssembly |
| Hosting | Server DocRaptor centralizzati (datacenter US) | Cloudflare Workers, ogni colo CF (300+ città) |
| Cold start | Pool di worker server-side | Boot di isolate V8, ms a una cifra |
| Compute per render | Pass di layout su HTML/CSS, poi Prince pagina | Composizione diretta, nessun pass di interpretazione layout |
| p50 per render | ~250–800 ms wall-clock (rete + render) | ~3–8 ms (rete + render) |
| Determinismo output | Alto (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:
- Parsare e validare l’HTML
- Risolvere la cascade CSS (eventualmente con estensioni proprie di Prince)
- Costruire l’albero di render
- Eseguire layout multi-pass (specialmente per tabelle che attraversano pagine, o colonne che si bilanciano)
- Risolvere riferimenti incrociati tra pagine
- 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:
- Scegli un tipo di documento da migrare. Inizia da quello con maggior volume — maggior risparmio, minor blast radius.
- Prendi l’interfaccia dati del template HTML (le variabili che interpola) e scrivi una piccola funzione
mapToDocumentRequest(data). - Itera contro il Playground finché l’output combacia.
- A/B in produzione: instrada 5 % del traffico a gPdf per due settimane. Diff i PDF. Confronta le fatture.
- Vai avanti o indietro in base ai dati, non alle vibrazioni.
TL;DR
| DocRaptor | gPdf | |
|---|---|---|
| Migliore per | HTML → PDF per contenuto arbitrario | JSON → PDF per documenti strutturati |
| Prezzo (100K pagine/mese) | $89 | $5 |
| Render p50 | 250–800 ms | 3–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.