Блог

gPdf vs DocRaptor: почему рендеринг на edge побеждает HTML-в-PDF

DocRaptor использует Prince для конвертации HTML в PDF на хостинговом бэкенде. gPdf рендерит структурированный JSON напрямую на edge Cloudflare. Разница цен — 18×. Вот почему это не наживка.

DocRaptor — компетентный продукт. Оборачивает Prince — золотой стандарт движков HTML-в-PDF — в хостинговый REST API с retry, асинхронными job-ами и приличной документацией. Существует более десяти лет, и для многих команд это очевидный выбор «не хочу самостоятельно эксплуатировать Prince».

Мы — инструмент другой формы. gPdf вообще не принимает HTML; берёт структурированный JSON и рендерит напрямую на edge Cloudflare. Разница прайс-листа при 100 000 страниц/месяц: 5 USD/мес. (gPdf Basic) vs $89/месяц (DocRaptor Basic) — около 18×. Эта разница не открывающая промо. Она структурная. Этот пост объясняет, почему структура производит эту цену, и где каждый инструмент действительно подходит.

Две архитектуры рядом

Слой DocRaptor (HTML → PDF) gPdf (JSON → PDF)
Вход HTML + CSS (с расширениями Prince paged-media) JSON DocumentRequest
Renderer Prince (компилированный C++ движок) Собственный движок Rust, скомпилированный в WebAssembly
Хостинг Централизованные серверы DocRaptor (датацентр US) Cloudflare Workers, каждый CF colo (300+ городов)
Холодный старт Серверный пул воркеров Загрузка V8 isolate, однозначные мс
Compute на рендер Pass layout по HTML/CSS, затем Prince пагинирует Прямая вёрстка, без pass интерпретации layout
p50 на рендер ~250–800 мс wall-clock (сеть + рендер) ~3–8 мс (сеть + рендер)
Детерминизм вывода Высокий (Prince зрелый) Байт-идентичный (тот же JSON → те же байты)

Если вы читаете эти две колонки как «универсальный HTML-принтер» vs «целенаправленно построенный рендерер документов», вы уже поняли архитектурное решение. Всё остальное (латентность, стоимость, даже списки функций) — ниже по течению этого единственного выбора.

Налог Prince

Prince хорош. Также делает работу, в которой большинство workflow счёт/чек/этикетка не нуждаются: реализовать CSS Paged Media — правила переноса страниц, бегущие headers, сноски, перекрёстные ссылки, генерируемый контент — для произвольного HTML, который пользователь может бросить.

Эта универсальность имеет runtime-стоимость. Чтобы пагинировать произвольный HTML, движок должен:

  1. Распарсить и валидировать HTML
  2. Разрешить CSS-каскад (потенциально с собственными расширениями Prince)
  3. Построить дерево рендера
  4. Запустить multi-pass layout (особенно для таблиц через страницы или балансирующих столбцов)
  5. Разрешить перекрёстные ссылки между страницами
  6. Эмитировать PDF-объекты

Большинство этих pass-ей — стоимость принятия HTML как входа. Если ваш вход уже структурированные данные (а почти всегда так — ваш счёт существует как JSON-объект до того, как вы оборачиваете его в HTML), вы платите за эти pass-ы compute и латентностью на каждом рендере, и они не добавляют ценности выводу.

gPdf полностью пропускает шаг интерпретации layout. JSON DocumentRequest уже структурно специфицирует layout страницы — { pages: [{ size, elements: [...] }] }. Renderer верстает элементы, пагинирует таблицы/списки детерминистично и эмитирует PDF. Никакого CSS-каскада для разрешения, никакого float-layout для вычисления, никакого pass разрешения перекрёстных ссылок.

Результат: тот же одностраничный счёт, занимающий ~300 мс на DocRaptor, занимает ~3 мс на gPdf. Мы быстрее не потому, что написали более быстрый Prince — мы быстрее потому, что не делаем большинства того, что делает Prince.

«Слишком дёшево, чтобы быть правдой» — это реальное возражение в закупках

Адресуем это напрямую, потому что всплывает в каждом B2B-звонке продаж.

«5 USD/мес. за 100 000 рендеров. DocRaptor — 89. Anvil — 0,10/PDF (то есть $10.000 при том же объёме). Что с вами не так?»

Три честные причины, по которым мы можем взимать это:

1. Мы не запускаем браузер

DocRaptor амортизирует Prince-инфраструктуру между клиентами. gPdf амортизирует один Cloudflare Worker, что стоит около $0,50/миллион запросов на Workers Bundled. С JSON-формой входа наш renderer берёт около 1,5 мс CPU на рендер. Накиньте 50% маржи и вы всё ещё в диапазоне центов-за-тысячу-рендеров. Арифметика — это цена.

2. Мы не запускаем control plane

Никаких асинхронных job-ов, callback-ов, очереди retry, хранилища документов, UI ссылок предпросмотра, multi-tenant БД. Каждый рендер — единственный round-trip к stateless-функции и обратно. Это удаляет всю поверхность ops, которую большинство компаний «PDF API» бюджетируют — что также является поверхностью, оправдывающей их цену.

3. Модель самоотбирается из workload-ов, на которых мы потеряли бы деньги

Если ваш документ действительно нуждается в HTML-в-PDF (60-страничный юридический договор, сложный CSS-Grid отчёт), вы отскочите от JSON-модели в первый час и пойдёте в DocRaptor всё равно. Нам не нужно защитно ценить эти workload-ы, потому что они саморутятся. Нужно только ценить длинный, но узкий хвост workload-ов «структурированные-данные-в-документ», где стоимость на рендер действительно крошечная.

Вместе: $5/100 000 — не loss-leader, это реальная себестоимость плюс маржа. Можем держать её там бесконечно, потому что базовый compute действительно настолько дёшев, когда вы не отгружаете браузер.

Где DocRaptor — правильный выбор

Стараемся не писать корыстные сравнения. Случаи, где DocRaptor реально побеждает:

  • Ваш вход — HTML, который вы не контролируете полностью. Отчёты, генерируемые пользователями, шаблоны третьих сторон, Markdown-из-CMS-рендерится-в-HTML. Не хотите писать JSON-mapper для произвольных входов.
  • Нужны функции CSS Paged Media, поддерживаемые Prince. Бегущие headers/footers по главам, сложный reflow сносок, именованные селекторы страниц, генерируемые оглавления, индексы. gPdf имеет структурированные эквиваленты для общего подмножества, но если вы живёте в селекторах @page :left, Prince — ваш друг.
  • У вас контент-команда, пишущая HTML/CSS, а не JSON. Не навязывайте JSON-workflow авторинга не-инженерной команде. Они вас возненавидят.
  • Async + callbacks + хранилище документов как сервис. DocRaptor хранит сгенерированные PDF и даёт вам подписанные URL для доставки. gPdf строго stateless — ваш код хранит результат.

Если вы в любом из этих вёдер, оставайтесь на DocRaptor. Это правильный инструмент.

Где gPdf — правильный выбор

Зеркальное отражение:

  • Ваши входы уже структурированные данные (строки БД, JSON API payload-ы, сообщения очереди).
  • Латентность важна — интерактивные checkout-flow, печать этикеток в реальном времени, генерация выписок по запросу.
  • Вам важна байт-идентичная воспроизводимость для тестов / audit trail / хранения электронных счетов.
  • Вы чувствительны к стоимости при любом объёме выше нескольких тысяч рендеров/месяц.
  • Нужны штрих-коды (GS1-128, QR, Data Matrix, PDF417, Aztec, MaxiCode) с суб-миллиметровой точностью.
  • Нужен PDF/A (1b/2b/3b/4) или вложения Factur-X / ZUGFeRD для compliance.
  • Вы предпочитаете не запускать pipeline JSON-в-HTML-в-PDF, когда можете запустить pipeline JSON-в-PDF.

Миграция механическая, не стратегическая

Распространённая забота: «Переход означает переписать все наши шаблоны». Обычно нет. Большинство шаблонов HTML-в-PDF — 20% layout (что один раз становится JSON-структурой) и 80% интерполяция данных (что точно одинаково независимо от того, что принимает renderer).

Практический путь:

  1. Выберите один тип документа для миграции. Начните с самого высокого объёма — самая большая экономия, самый малый радиус взрыва.
  2. Возьмите интерфейс данных HTML-шаблона (переменные, которые он интерполирует) и напишите небольшую функцию mapToDocumentRequest(data).
  3. Итерируйте против Playground, пока вывод не совпадёт.
  4. A/B в продакшене: маршрутизируйте 5% трафика на gPdf две недели. Diff PDF. Сравните счета.
  5. Двигайтесь вперёд или назад на основе данных, а не вибраций.

Мы видели, как команды проходили этот путь за один sprint и уже в следующем месяце забирали около 90% экономии на PDF-счете. Мы также видели команды, которые понимали, что их workload действительно относится к HTML-to-PDF, и оставались на DocRaptor — с нашим полным согласием.

TL;DR

DocRaptor gPdf
Лучше для HTML → PDF для произвольного контента JSON → PDF для структурированных документов
Цена (100 000 страниц/месяц) $89 $5
Рендер p50 250–800 мс 3–8 мс
Edge-deployed ❌ централизованный ✅ 300+ Cloudflare colos
Async + storage ✅ включено ❌ stateless по дизайну
PDF/A + Factur-X / ZUGFeRD ⚠️ через расширения Prince ✅ встроено

Если ваши документы — структурированные данные, замаскированные под HTML для renderer-а, вы платите за шаг трансляции, который не должен существовать. Попробуйте Playground — опишите один из ваших счетов в JSON, отрендерите в браузере менее чем за 5 мс, посмотрите, совпадает ли разрыв с вашей интуицией.