Blog

gPdf vs DocRaptor: por que renderização no edge vence HTML-para-PDF

DocRaptor usa Prince para converter HTML em PDF em backend hospedado. gPdf renderiza JSON estruturado diretamente no edge da Cloudflare. A diferença de preço é 18×. Aqui está por que isso não é uma isca.

DocRaptor é um produto competente. Encapsula Prince — o motor padrão-ouro de HTML-para-PDF — em uma API REST hospedada, com retries, jobs assíncronos e documentação decente. Existe há mais de uma década e para muitas equipes é a escolha óbvia «não quero rodar Prince eu mesmo».

Somos uma ferramenta de outra forma. gPdf não aceita HTML de forma alguma; recebe JSON estruturado e renderiza diretamente no edge da Cloudflare. A diferença de preço de tabela em 100K páginas/mês: $5/mês (gPdf Basic) vs $89/mês (DocRaptor Basic) — cerca de 18×. Essa diferença não é promoção de abertura. É estrutural. Este post explica por que a estrutura produz esse preço e onde cada ferramenta realmente se encaixa.

As duas arquiteturas, lado a lado

CamadaDocRaptor (HTML → PDF)gPdf (JSON → PDF)
EntradaHTML + CSS (com extensões Prince paged-media)JSON DocumentRequest
RendererPrince (engine C++ compilada)Engine Rust própria, compilada para WebAssembly
HospedagemServidores DocRaptor centralizados (datacenter US)Cloudflare Workers, todo colo CF (300+ cidades)
Cold startPool de workers do lado servidorBoot de isolate V8, ms de um dígito
Compute por renderPass de layout sobre HTML/CSS, depois Prince paginaComposição direta, sem pass de interpretação de layout
p50 por render~250–800 ms wall-clock (rede + render)~3–8 ms (rede + render)
Determinismo da saídaAlto (Prince é maduro)Byte-idêntico (mesmo JSON → mesmos bytes)

Se você lê essas duas colunas como «impressora HTML genérica» vs «renderer de documentos construído para o propósito», já entendeu a decisão arquitetural. Tudo mais (latência, custo, até as listas de features) é a jusante dessa única escolha.

O imposto Prince

Prince é bom. Também faz um trabalho que a maioria dos workflows fatura/recibo/etiqueta não precisa: implementar CSS Paged Media — regras de quebra de página, headers contínuos, notas de rodapé, referências cruzadas, conteúdo gerado — para HTML arbitrário que o usuário possa jogar.

Essa generalidade tem custo de runtime. Para paginar HTML arbitrário, a engine deve:

  1. Parsear e validar o HTML
  2. Resolver cascata CSS (potencialmente com extensões próprias do Prince)
  3. Construir árvore de render
  4. Executar layout multi-pass (especialmente para tabelas que cruzam páginas, ou colunas balanceando)
  5. Resolver referências cruzadas entre páginas
  6. Emitir objetos PDF

A maioria desses passes é o custo de aceitar HTML como entrada. Se sua entrada já é dado estruturado (e quase sempre é — sua fatura existe como objeto JSON antes de envolvê-la em HTML), você está pagando por esses passes em compute e latência a cada render, e eles não adicionam valor à saída.

gPdf pula completamente o passo de interpretação de layout. O DocumentRequest JSON já especifica o layout de página estruturalmente — { pages: [{ size, elements: [...] }] }. O renderer compõe os elementos, pagina tabelas/listas deterministicamente e emite PDF. Sem cascata CSS para resolver, sem layout de floats para computar, sem pass de resolução de referências cruzadas.

Resultado: a mesma fatura de uma página que leva ~300 ms no DocRaptor leva ~3 ms no gPdf. Não somos mais rápidos porque escrevemos um Prince mais rápido — somos mais rápidos porque não fazemos a maior parte do que Prince faz.

«Barato demais para ser verdade» é uma objeção real de procurement

Vamos endereçar isso diretamente porque surge em toda call de vendas B2B.

«$5/mês para 100K renders. DocRaptor é $89. Anvil é $0,10/PDF (ou seja $10.000 no mesmo volume). O que há de errado com vocês?»

Três razões honestas pelas quais podemos cobrar isso:

1. Não rodamos um navegador

DocRaptor amortiza infraestrutura Prince entre clientes. gPdf amortiza um Cloudflare Worker, que custa cerca de $0,50/milhão de requests no Workers Bundled. Com entrada em forma JSON, nosso renderer leva cerca de 1,5 ms de CPU por render. Empilhe 50% de margem e você ainda está na faixa de centavos-por-mil-renders. A aritmética é o preço.

2. Não rodamos um control plane

Sem jobs assíncronos, sem callbacks, sem fila de retry, sem armazenamento de documentos, sem UI de link de preview, sem banco multi-tenant. Cada render é um único round-trip a uma função stateless e volta. Isso remove toda a superfície ops que a maioria das empresas «PDF API» orçam — que é também a superfície que justifica o preço delas.

3. O modelo se autoseleciona fora dos workloads em que perderíamos dinheiro

Se seu documento genuinamente precisa de HTML-para-PDF (contrato legal de 60 páginas, relatório CSS-Grid complexo), você vai ricochetear do modelo JSON na primeira hora e ir para DocRaptor de qualquer forma. Não precisamos precificar defensivamente para esses workloads porque eles se autoroteiam. Só precisamos precificar para a cauda longa mas estreita de workloads «dados-estruturados-para-documento», onde o custo por render é genuinamente minúsculo.

Juntos: $5/100K não é loss-leader, é o custo de bens vendidos real mais margem. Podemos manter isso indefinidamente porque o compute subjacente é tão barato quando você não embarca um navegador.

Onde DocRaptor é a escolha certa

Tentamos não escrever comparativos auto-interessados. Os casos onde DocRaptor genuinamente vence:

  • Sua entrada é HTML que você não controla completamente. Relatórios gerados por usuários, templates de terceiros, Markdown-de-CMS-renderizado-para-HTML. Você não quer escrever um mapper JSON para entradas arbitrárias.
  • Você precisa de features CSS Paged Media suportadas por Prince. Headers/footers contínuos por capítulo, reflow complexo de notas de rodapé, seletores de página nomeados, índices e sumários gerados. gPdf tem equivalentes estruturados para o subconjunto comum, mas se você vive em seletores @page :left, Prince é seu amigo.
  • Você tem time de conteúdo escrevendo HTML/CSS, não JSON. Não imponha workflow de autoria JSON a um time não-engineering. Eles vão te odiar.
  • Async + callbacks + armazenamento de documentos como serviço. DocRaptor armazena PDFs gerados e te dá URLs assinadas para entrega. gPdf é estritamente stateless — seu código armazena o resultado.

Se você está em qualquer desses baldes, fique no DocRaptor. É a ferramenta certa.

Onde gPdf é a escolha certa

A imagem espelho:

  • Suas entradas são já dados estruturados (linhas de banco, payloads JSON API, mensagens de fila).
  • Latência importa — fluxos de checkout interativo, impressão de etiquetas em tempo real, geração de extratos sob demanda.
  • Você se importa com reprodutibilidade byte-idêntica para testes / trilhas de auditoria / retenção de notas fiscais eletrônicas.
  • Você é sensível a custo em qualquer volume acima de alguns milhares de renders/mês.
  • Você precisa de códigos de barras (GS1-128, QR, Data Matrix, PDF417, Aztec, MaxiCode) com precisão sub-milimétrica.
  • Você precisa de PDF/A (1b/2b/3b/4) ou anexos Factur-X / ZUGFeRD para compliance — particularmente relevante para o mandato brasileiro NF-e (em vigor há mais de uma década) e os mandatos europeus em rollout 2024-2027.
  • Você prefere não rodar um pipeline JSON-para-HTML-para-PDF quando pode rodar um pipeline JSON-para-PDF.

Nota específica para times no Brasil sobre NF-e

Se seu contexto é o ecossistema brasileiro de Nota Fiscal Eletrônica (NF-e) — XML estruturado obrigatório transmitido via SEFAZ desde 2008, com DANFE (representação visual em PDF) — a arquitetura conceitual é idêntica ao Factur-X: XML máquina-legível + representação visual humana. gPdf produz tanto o DANFE quanto pode anexar o XML NF-e via PDF/A-3:

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

Para integração internacional (clientes EU exigindo Factur-X, ou exportação para mercados com mandatos próprios), o mesmo endpoint com format: factur-x produz o formato EN 16931 padrão.

Sem post-pass Ghostscript, sem segunda ferramenta para anexar o XML, sem loteria de validação entre passos. Os bytes de saída são byte-idênticos entre versões da engine, então seu hash de retenção para a obrigação de guarda fiscal de 5 anos pode permanecer estável.

Migração é mecânica, não estratégica

Uma preocupação comum: «Trocar significa reescrever todos os nossos templates». Geralmente não. A maioria dos templates HTML-para-PDF são 20% layout (que vira estrutura JSON uma vez) e 80% interpolação de dados (que é exatamente o mesmo independente do que o renderer aceita).

Caminho prático:

  1. Escolha um tipo de documento para migrar. Comece pelo de maior volume — maior economia, menor raio de explosão.
  2. Pegue a interface de dados do template HTML (as variáveis que ele interpola) e escreva uma pequena função mapToDocumentRequest(data).
  3. Itere contra o Playground até a saída combinar.
  4. A/B em produção: roteie 5% do tráfego para gPdf por duas semanas. Diff os PDFs. Compare faturas.
  5. Avance ou recue baseado em dados, não vibrações.

TL;DR

DocRaptorgPdf
Melhor paraHTML → PDF para conteúdo arbitrárioJSON → PDF para documentos estruturados
Preço (100K páginas/mês)$89$5
Render p50250–800 ms3–8 ms
Edge-deployed❌ centralizado✅ 300+ colos Cloudflare
Async + storage✅ incluído❌ stateless por design
PDF/A + Factur-X / ZUGFeRD⚠️ via extensões Prince✅ embutido

Se seus documentos são dados estruturados disfarçados de HTML para um renderer, você está pagando por um passo de tradução que não precisa existir. Experimente o Playground — descreva uma de suas faturas em JSON, renderize-a no seu navegador em menos de 5 ms, veja se a diferença bate com sua intuição.