DocRaptor は有能なプロダクトです。Prince — HTML-to-PDF のゴールドスタンダードエンジン — をホスト型 REST API でラップし、リトライ、非同期ジョブ、まともなドキュメントを備えています。10 年以上前からあり、多くのチームにとっては「自分で Prince を運用したくない」場合の明らかな選択肢です。
私たちは別の形のツールです。gPdf は HTML をまったく受け取りません。構造化 JSON を受け取り、Cloudflare のエッジで直接 PDF にレンダリングします。月 100K ページでの定価差: $5/月 (gPdf Basic) vs $89/月 (DocRaptor Basic) — 約 18 倍。この差はオープニングプロモーションではありません。構造的なものです。本記事は構造がなぜその価格を生むのか、そして各ツールが実際にどこに適しているのかを説明します。
2 つのアーキテクチャを並べて
| レイヤー | DocRaptor (HTML → PDF) | gPdf (JSON → PDF) |
|---|---|---|
| 入力 | HTML + CSS(Prince paged-media 拡張あり) | JSON DocumentRequest |
| レンダラー | Prince(コンパイル済み C++ エンジン) | 自社 Rust エンジン、WebAssembly にコンパイル |
| ホスティング | DocRaptor 中央集約サーバー(US データセンター) | Cloudflare Workers、すべての CF colo(300+ 都市) |
| コールドスタート | サーバー側ワーカープール | V8 isolate ブート、1 桁ミリ秒 |
| レンダーあたり計算 | HTML/CSS のレイアウトパス、その後 Prince がページ分割 | 直接組版、レイアウト解釈パスなし |
| レンダーあたり p50 | ~250–800 ms wall-clock(ネットワーク + レンダリング) | ~3–8 ms(ネットワーク + レンダリング) |
| 出力決定論性 | 高い(Prince は成熟) | バイト同一(同じ JSON → 同じバイト) |
これら 2 列を「汎用 HTML プリンター」vs「目的別ドキュメントレンダラー」と読めば、すでにアーキテクチャの決定を理解しています。それ以外(レイテンシ、コスト、機能リストさえも)は、その 1 つの選択の下流にあります。
Prince 税
Prince は良いものです。また、ほとんどの請求書/領収書/ラベルワークフローが必要としない仕事もしています: ユーザーが投げ込むかもしれない任意の HTML に対して CSS Paged Media — 改ページルール、running header、脚注、相互参照、生成コンテンツ — を実装することです。
その汎用性にはランタイムコストがあります。任意の HTML をページ分割するには、エンジンは:
- HTML をパース、検証
- CSS カスケードを解決(場合によっては Prince 独自の拡張あり)
- レンダーツリーを構築
- マルチパスレイアウトを実行(特にページをまたぐテーブル、バランスする列)
- ページ間の相互参照を解決
- PDF オブジェクトを発行
これらのパスのほとんどは、HTML を入力として受け入れるコストです。入力がすでに構造化データ(ほぼ常にそう — 請求書は HTML にラップする前から JSON オブジェクトとして存在)であれば、それらのパスを毎回のレンダーで計算とレイテンシで支払い、出力に価値を加えません。
gPdf はレイアウト解釈ステップを完全にスキップします。JSON DocumentRequest はすでにページレイアウトを構造的に指定 — { pages: [{ size, elements: [...] }] }。レンダラーは要素を組版し、テーブル/リストを決定論的にページ分割し、PDF を発行します。解決すべき CSS カスケードなし、計算すべきフロートレイアウトなし、相互参照解決パスなし。
結果: DocRaptor で ~300 ms かかる同じ 1 ページの請求書が、gPdf では ~3 ms。私たちは速い Prince を書いたから速いのではなく、Prince がやっていることのほとんどをやらないから速いのです。
「安すぎて怪しい」は本物の調達異論です
直接対処しましょう、すべての B2B 営業電話で出てくるからです。
「100K レンダーで $5/月。DocRaptor は $89。Anvil は $0.10/PDF(つまり同じボリュームで $10,000)。何が変なの?」
この値段で請求できる 3 つの正直な理由:
1. ブラウザを動かしていない
DocRaptor は Prince インフラを顧客間で償却します。gPdf は Cloudflare Worker を償却し、Workers Bundled で約 $0.50/百万リクエストです。JSON 形式の入力で、レンダラーはレンダーあたり約 1.5 ms の CPU を使います。50% のマージンを積んでも、千レンダーあたりセント単位の範囲です。算術が価格です。
2. コントロールプレーンを動かしていない
非同期ジョブなし、コールバックなし、リトライキューなし、ドキュメントストレージなし、プレビューリンク UI なし、マルチテナント DB なし。各レンダーはステートレス関数への単一往復です。これにより、ほとんどの「PDF API」企業が予算を割く ops 表面全体が削除されます — それは彼らの価格を正当化する表面でもあります。
3. モデルが赤字になるワークロードを自己選択排除
ドキュメントが本当に HTML-to-PDF を必要とするなら(60 ページの法律契約、複雑な CSS-Grid レポート)、最初の 1 時間で JSON モデルから跳ね返り、結局 DocRaptor に行きます。それらのワークロードを防御的に価格設定する必要はありません。自動ルーティングされるからです。「構造化データ→ドキュメント」という長くて狭い裾だけを価格設定すればよく、そこではレンダーあたりのコストが本当に小さいのです。
合わせて: $5/100K は損失リーダーではなく、実際の売上原価+マージンです。ブラウザを出荷しないとき、基盤の compute が本当にそれほど安いので、無期限にそこに保てます。
DocRaptor が正解の場合
自利的な比較を書かないように努めています。DocRaptor が真に勝つケース:
- 入力が完全に制御していない HTML である。 ユーザー生成レポート、サードパーティテンプレート、CMS から HTML にレンダリングされた Markdown。任意の入力に対して JSON マッパーを書きたくない。
- Prince がサポートする CSS Paged Media 機能が必要。 章ごとの running header/footer、複雑な脚注の reflow、名前付きページセレクタ、生成された目次・索引。gPdf は共通サブセットに対する構造化された等価物を持っていますが、
@page :leftセレクタの中で生きているなら Prince が友です。 - コンテンツチームが HTML/CSS を書き、JSON は書かない。 非エンジニアリングチームに JSON オーサリングワークフローを強制しないでください。嫌われます。
- 非同期 + コールバック + ドキュメントストレージサービス。 DocRaptor は生成された PDF を保存し、配信用の署名付き URL を提供します。gPdf は厳密にステートレス — コードが結果を保存します。
これらのバケットのいずれかに該当するなら、**DocRaptor のままで。**それが正しいツールです。
gPdf が正解の場合
鏡像:
- 入力がすでに構造化データ(DB 行、JSON API ペイロード、キューメッセージ)。
- レイテンシが重要 — インタラクティブなチェックアウトフロー、リアルタイムラベル印刷、オンデマンド明細生成。
- テスト/監査証跡/電子インボイス保管のためにバイト同一の再現性を気にする。
- 月数千レンダー以上の任意のボリュームでコストに敏感。
- バーコード(GS1-128、QR、Data Matrix、PDF417、Aztec、MaxiCode)をサブミリ精度で必要。
- PDF/A(1b/2b/3b/4)または Factur-X / ZUGFeRD 添付がコンプライアンスのために必要 — 特に 2023 年 10 月から始まった日本のインボイス制度との連携、および 2026 年 9 月からのフランス B2B 義務に関連。
- JSON-to-HTML-to-PDF パイプラインを実行できるなら、JSON-to-PDF パイプラインを実行したい。
日本のチーム向けの具体的なメモ
日本のインボイス制度(2023 年 10 月開始の適格請求書等保存方式)の文脈では、適格請求書発行事業者の登録番号、税率ごとの取引額、消費税額の明示など、構造化された情報が必須です。EU の Factur-X / ZUGFeRD ほど厳格な PDF/A-3 + XML 二層構造は法的に要求されていませんが、グローバルに事業展開する場合や Peppol(日本でも 2024 年から推進)対応のために、同じ仕組みで両方のフォーマットを満たせます:
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 invoice.pdf
Ghostscript ポストパスなし、XML を添付するための 2 つ目のツールなし、ステップ間の検証宝くじなし。出力バイトはエンジンバージョン間でバイト同一なので、7 年の電子帳簿保存法義務のための保管ハッシュは安定して維持できます。
移行は機械的、戦略的ではない
よくある懸念: 「切り替えはすべてのテンプレートを書き直すことを意味する」。普通はそうではありません。ほとんどの HTML-to-PDF テンプレートは 20% がレイアウト(一度 JSON 構造になる)と 80% がデータ補間(レンダラーが何を受け取っても全く同じ)です。
実用的な道筋:
- 移行する1 つのドキュメントタイプを選ぶ。最大ボリュームから始める — 最大の節約、最小の爆発半径。
- HTML テンプレートのデータインターフェース(補間する変数)を取り、小さな
mapToDocumentRequest(data)関数を書く。 - 出力が一致するまで Playground に対して反復。
- 本番で A/B: トラフィックの 5% を 2 週間 gPdf にルート。PDF を diff。請求を比較。
- データに基づいて前進または後退、雰囲気ではなく。
TL;DR
| DocRaptor | gPdf | |
|---|---|---|
| 最適 | 任意のコンテンツの HTML → PDF | 構造化ドキュメントの JSON → PDF |
| 価格(月 100K ページ) | $89 | $5 |
| レンダー p50 | 250–800 ms | 3–8 ms |
| エッジデプロイ | ❌ 中央集約 | ✅ 300+ Cloudflare colos |
| 非同期 + ストレージ | ✅ 含む | ❌ 設計上ステートレス |
| PDF/A + Factur-X / ZUGFeRD | ⚠️ Prince 拡張経由 | ✅ 内蔵 |
ドキュメントがレンダラー向けに HTML として偽装された構造化データであれば、存在する必要のない翻訳ステップに支払っています。Playground を試してみてください — 請求書の 1 つを JSON で記述し、ブラウザで 5 ms 未満でレンダリングし、ギャップが直感と合うか見てみてください。