Puppeteer vs PDF API:パフォーマンス・コスト・運用負荷の比較
Puppeteerは少量のPDF生成には十分機能します。しかし本番運用でスケールしていくと、メモリスパイク・Chromiumバージョン管理・ブラウザプールの実装など、PDF生成そのものとは無関係な運用負荷がエンジニアの時間を圧迫し始めます。マネージドPDF APIはその運用負荷をリクエスト単位のコストと交換するアプローチです。
この記事では、パフォーマンス・メモリ・同時処理数・コスト・運用複雑性という観点で両アプローチを比較します。既に移行を決めていて手順コードが必要な方はPuppeteerからPDF API移行ガイドをご覧ください。
各アプローチが実際に何を意味するか
Puppeteer自前運用
Puppeteerはheadless Chromiumを操作するNode.jsライブラリです。本番でPDF生成に使うには以下が必要です。
- Chromiumバージョンをピン留めし、セキュリティパッチが出るたびに更新する
- コールドスタートを避けるためブラウザプールを構築・維持する
- メモリ制限・ゾンビプロセス・graceful shutdownを処理する
- DockerイメージにChromiumを含める(約300MB増)
- Chromiumのダウンロード失敗によるCI/CDの破損を管理する
これらの作業はPDFを生成することとは直接関係ありません。ブラウザを本番で動かすためのコストです。
マネージドPDF API
マネージドPDF API(例:FUNBREW PDF)はHTTPでHTMLペイロードを受け取り、PDFバイトを返します。自サーバーにChromiumは不要です。スケーリング・エンジンアップグレード・同時処理数はすべてサービス側が管理します。
判断のポイントは「Chromiumをオフロードすることでエンジニアリングコストをどれだけ削減できるか」とAPIのリクエスト単価を比較することです。
パフォーマンス比較
レスポンスタイム
| シナリオ | Puppeteer コールドスタート | Puppeteer ウォーム | FUNBREW PDF API |
|---|---|---|---|
| シンプルなHTML(〜10KB) | 3,000〜5,000ms | 500〜800ms | 300〜600ms |
| 画像入りHTML(〜100KB) | 4,000〜8,000ms | 800〜1,500ms | 500〜1,200ms |
| 複雑なCSS + 画像 | 6,000〜15,000ms | 1,500〜3,000ms | 800〜2,000ms |
| AWS Lambda(サーバーレス) | 8,000〜15,000ms | — | 300〜600ms |
コールドスタートの数値にはChromiumの起動時間が含まれます。ウォーム状態のブラウザプールは単純なドキュメントでは競争力がありますが、複雑なテンプレートではAPIのネットワーク往復よりもページレンダリングに時間がかかります。
サーバーレス環境(Lambda・Vercel・Cloudflare Workers)では、リクエストのたびにサンドボックス内でChromiumを起動する必要があるため、Puppeteerのコールドスタートが特に問題になります。マネージドAPIは自サーバー側にコールドスタートのペナルティを発生させません。Lambda固有のデプロイについてはサーバーレス向けPDF APIガイドをご覧ください。
メモリ使用量
Puppeteer(ブラウザプール、3プロセス):
アイドル時: 600MB〜1.5GB
PDF生成中: 1GB〜2GB+
ピーク(10並行): 3GB+
マネージドPDF API(HTTPクライアントのみ):
アイドル時: < 10MB
PDF生成中: < 50MB(HTTPレスポンスのバッファリング)
ピーク(100並行): ほぼ同様(自サーバー側でのスケーリング不要)
t3.medium(4GB RAM)の場合、3プロセスのPuppeteerブラウザプールはアプリケーション用に1〜2GBしか残りません。同時処理数を増やすには大きなインスタンスか、PDF専用サービスの分離が必要です。
Dockerイメージサイズ
# Puppeteerイメージ
FROM node:20
RUN apt-get install -y chromium # +300MB
RUN npm install puppeteer # +200MB
# 合計: 1GB以上
# APIクライアントのみ
FROM node:20-alpine
# Chromium不要
# 合計: ~150MB
イメージを小さくすることで、CIビルドの高速化・コンテナ起動時間の短縮・レジストリストレージコストの削減が見込めます。コンテナデプロイのパターンはDocker・KubernetesでのPDF API運用ガイドをご覧ください。
同時処理数
Puppeteer(2GBサーバー、3プロセスのブラウザプール):
安全な最大同時数: 3〜5件
超えた場合: キューイングまたはOOM
マネージドPDF API:
最大同時数: 実用上制限なし(レート制限依存)
スケーリング: APIプロバイダー側が処理
50件のPDFを同時生成する必要がある場合、Puppeteerでは非常に大きなインスタンスか分散システムが必要です。マネージドAPIではサービスレベルで対応します。
コスト比較
Puppeteer自前運用のコスト
インフラ
AWS t3.medium(2vCPU / 4GB RAM):
オンデマンド: 約$33/月
リザーブド: 約$20/月
3プロセスのPuppeteerプールとアプリケーション用のヘッドルームを確保するための最小構成。
バーストトラフィック時は大きなインスタンスかオートスケーリングが必要。
エンジニアリングとメンテナンス
初期実装(ブラウザプール・タイムアウト・リトライ): 8〜16時間
Chromiumバージョンアップ(年3〜4回・1回2〜4時間): 6〜16時間/年
障害対応(OOM・ゾンビプロセス・月1回程度): 2〜8時間/回
年間メンテナンスコスト試算: エンジニア時間 20〜50時間
時給$100換算で年間30時間のメンテナンスは$3,000のコストになります。Chromiumのクラッシュデバッグへのコンテキストスイッチによる生産性低下は加味していません。
CI/CD
Chromiumダウンロード(100〜200MB)はビルドを遅くします。1GBを超えるDockerイメージはプッシュ/プル時間を増加させ、レジストリストレージも圧迫します。
マネージドAPIのコスト
FUNBREW PDF 無料プラン: 月30件まで無料
有料プラン: 従量課金(/pricing参照)
エンジニアリングコスト: ほぼゼロ(APIクライアント変更のみ)
損益分岐点の目安
少量(月100件未満):
自前運用: サーバー費 + エンジニア時間 >> API費用
→ APIが明らかに有利
中量(月100〜10,000件):
自前運用: $30〜100 サーバー + 20〜50時間メンテナンス
API: 従量課金
→ メンテナンス時間を含めるとAPIが有利なケースが多い
大量(月10,000件以上):
自前運用: 専用インフラ・専任運用チームが必要
API: プロバイダー側でスケール
→ 要件次第だが、API専業チームのスケール効率には勝てない
多くのチームが過小評価するコストがエンジニアの機会コストです。Chromium管理に費やした時間はプロダクト開発に使えません。
運用比較
| 項目 | Puppeteer(自前運用) | マネージドPDF API |
|---|---|---|
| Chromiumアップグレード | バージョン固定・全更新をテスト | 不要 |
| セキュリティパッチ | 手動・ChromiumのCVEに対応 | プロバイダーが管理 |
| 同時処理数のスケール | 手動チューニングまたはインフラ拡張 | APIが自動スケール |
| 監視対象 | ブラウザヘルス・メモリ・ゾンビプロセス | HTTPエラーレートのみ |
| サーバーレス対応 | Lambdaレイヤー・サイズ上限の回避策 | そのまま動作 |
| Dockerイメージ | 1GB+(Chromium込み) | 軽量(Chromium不要) |
| オンコールの原因 | OOMクラッシュ・プロセスリーク | プロバイダーのHTTP 5xx |
Chromiumを自前ホストする際のセキュリティ考慮についてはPDF APIセキュリティガイドをご覧ください。
CSSとレンダリングの互換性
FUNBREW PDFはChromiumベースのエンジンを使用しているため、ほとんどのテンプレートでPuppeteerと視覚的に同等の出力が得られます。同じCSSエンジン・同じフォントレンダリング・同じ@page処理です。
評価時に確認すべき2つのエッジケース:
page.emulateMediaType('screen'): これをPuppeteerで使っていた場合、APIはデフォルトでprintメディアタイプを使用します。@media screenと@media printのルールを確認してください。page.evaluate()によるDOM操作: APIはアプリケーションのJavaScriptを実行しません。その処理をテンプレートレンダリングのステップに移動させてください。
移行時のCSS詳細についてはHTML to PDF CSSのコツをご覧ください。
どちらを選ぶべきか
Puppeteer自前運用を選ぶ場合
- プロトタイプ段階で月30件未満(コストはほぼゼロ)
- セキュリティポリシーで外部サービスへのHTML送信が禁止されている
- PDF生成前に
page.evaluate()で複雑なJavaScriptを実行する必要があり、サーバーサイドレンダリングに移せない - ブラウザテストでPuppeteerを多用しており、PDF生成は副次的な機能に過ぎない
マネージドPDF APIを選ぶ場合
- PDF生成がプロダクトの重要な機能になっている
- サーバーレスインフラ(Lambda・Vercel・Cloudflare Workers)を利用している
- OOMクラッシュ・Chromiumアップグレードの破損・CI/CDの遅延がすでに発生している
- Dockerイメージを軽量に保ちたい
- 1サーバーで処理できる以上の同時処理数が必要
段階的な移行パス
一度に全部移行する必要はありません。よくある方法はラッパー関数を導入することです。
// 薄いラッパー — まずPuppeteerを呼ぶ
async function generatePdf(html, options = {}) {
// フェーズ1: Puppeteer
return generatePdfWithPuppeteer(html, options);
// フェーズ2: 準備できたらAPIに切り替え
// return generatePdfWithApi(html, options);
}
フィーチャーフラグを使ってPDFの種類ごとに段階的に移行します(請求書 → レポート → 証明書の順など)。これにより、チームがAPIの出力に自信を持てるまでロールバック経路が確保されます。完全な移行手順はPuppeteerからPDF API移行ガイドをご覧ください。
クイックスタートコード
APIを試してみる場合、最小のNode.js実装は以下の通りです。
async function generatePdf(html) {
const response = await fetch('https://pdf.funbrew.cloud/api/v1/pdf/generate', {
method: 'POST',
headers: {
'X-API-Key': process.env.FUNBREW_PDF_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
html,
options: {
format: 'A4',
margin: { top: '20mm', bottom: '20mm', left: '15mm', right: '15mm' },
print_background: true,
},
}),
});
if (!response.ok) throw new Error(`API error: ${response.status}`);
return Buffer.from(await response.arrayBuffer());
}
コードを書く前にPlaygroundでHTMLをテストしてください。無料プランで月30件まで無料で試せます。Python・PHP・Ruby・Goのコード例は言語別APIクイックスタートをご覧ください。
まとめ
| Puppeteer(自前運用) | マネージドPDF API | |
|---|---|---|
| コールドスタート | 3〜8s(Lambda)・1〜3s(ウォーム) | なし |
| リクエストあたりメモリ | 200〜500MB | < 10MB |
| Dockerイメージ | 1GB+ | ~150MB |
| 同時処理の上限 | サーバーRAMに依存 | レート制限に依存 |
| 年間メンテナンス | 20〜50エンジニア時間 | ほぼゼロ |
| 費用開始 | ~月30件からコスト発生 | 無料から始められる |
Puppeteerは出発点として合理的です。しかしPDF生成が本番ワークロードになった時点で、マネージドPDF APIの方が通常は優れた選択肢になります。ほぼあらゆる現実的な規模で、運用コストの削減がAPIのリクエスト費用を上回ります。移行を判断する前にPlaygroundでテンプレートの出力品質を確認してください。
関連リンク
- PuppeteerからPDF API移行ガイド — Before/Afterコード付きの移行手順
- HTML to PDF API比較 2026年版 — wkhtmltopdf・Gotenbergを含む広範な比較
- 言語別APIクイックスタート — Node.js・Python・PHP・Ruby・Goのコード例
- サーバーレス向けPDF APIガイド — Lambda・Cloudflare Workersデプロイ
- Docker・KubernetesでのPDF API運用ガイド — コンテナベースのデプロイパターン
- PDF APIエラーハンドリング完全ガイド — リトライロジックとレジリエンスパターン
- PDF APIセキュリティガイド — PDF生成のセキュリティベストプラクティス