$ cat post.metadata

Cloudflare Workers vs AWS Lambda vs Vercel -- GTMエンジニアリングのインフラ実測比較

GTMエンジニアリングインフラ

GTMエンジニアリングのワークロードでCloudflare Workers、AWS Lambda、Vercelを実測比較する。CRM API中継、AIパイプライン処理、Webhook受信の3つの典型シナリオでレイテンシ・コスト・DXを検証。

$ cat post.content | render --format=markdown

Cloudflare Workers vs AWS Lambda vs Vercel -- GTMエンジニアリングのインフラ実測比較

この記事の位置づけ

Phase 1の最後の記事となる。技術選定フレームワークでは、事業ドメインとコストから逆算してインフラを選ぶ判断基準を整理した。この記事では、そのフレームワークを実測データで裏付ける。

GTMエンジニアリングの典型的なワークロードを3つ取り上げ、Cloudflare Workers、AWS Lambda、Vercel Edge Functions / Serverless Functionsの3プラットフォームで同一のビジネスロジックを動かし、レイテンシ・コスト・開発体験を比較する。

感想ではなく数字で判断できるようにする。

比較の前提と方法論

3つの典型的ワークロード

AIパイプラインの記事で構築した営業パイプラインを分解すると、GTMエンジニアのインフラワークロードは3パターンに集約される。

シナリオ内容特性
CRM API中継HubSpot/Salesforce APIへのプロキシ + データ変換低レイテンシ、軽量処理、高頻度
AIパイプライン処理Claude API呼び出し + リードデータ変換 + CRM書き戻し長時間実行、ストリーミング、中頻度
Webhook受信CRMイベント受信 → 署名検証 → 後続処理トリガー即応性、同時実行、スパイク対応

各プラットフォームの基本スペック

2026年4月時点の公開スペックを整理する。

スペックCloudflare WorkersAWS LambdaVercel
ランタイムV8 isolateNode.js / Bun / カスタムランタイムNode.js (Serverless) / V8 (Edge)
コールドスタートなし(V8 isolate)100ms-数秒(VPC接続時は増大)Edge: なし / Serverless: 100ms-数秒
最大実行時間30秒(Free)/ 15分(Paid)15分10秒(Hobby)/ 60秒(Pro Edge)/ 300秒(Pro Serverless)
メモリ128MB128MB-10GBEdge: 128MB / Serverless: 1-3GB
リージョングローバルエッジ(300+拠点)任意リージョン選択グローバルエッジ + リージョナル
ネイティブストレージKV, D1, R2, Durable ObjectsS3, DynamoDB, SQSKV, Blob, Postgres
TypeScriptネイティブ対応ネイティブ対応ネイティブ対応

計測環境

  • 計測リージョン: 東京(ap-northeast-1相当)
  • 計測ツール: k6(Grafana)でp50/p95/p99を取得
  • リクエスト数: 各シナリオ10,000リクエスト(100並列 x 100回)
  • フレームワーク: 全プラットフォームでHonoを使用
  • 計測期間: 平日の業務時間帯(10:00-17:00 JST)に実施

シナリオ1: CRM API中継

ユースケース

営業ダッシュボードからHubSpot APIへのリクエストを中継する。直接CRM APIを叩かず、中間にAPIプロキシを置く設計は、GTMエンジニアリングでは定石だ。理由は3つある。

  1. レート制限の集中管理: HubSpotの110リクエスト/10秒を超えないよう制御する
  2. データ変換: CRM固有のフィールド名をアプリケーション側の統一スキーマに変換する
  3. キャッシュ: 同じコンタクト情報への繰り返しアクセスをキャッシュで吸収する

Hono実装(共通ビジネスロジック)

3プラットフォームで同一のビジネスロジックを動かす。Honoを使えば、エントリポイントだけが異なり、ルーティングとビジネスロジックは共有できる。

typescript
// src/routes/crm-proxy.ts -- 3プラットフォーム共通 import { Hono } from 'hono' import { z } from 'zod' import { zValidator } from '@hono/zod-validator' const crmProxy = new Hono() const ContactQuerySchema = z.object({ email: z.string().email().optional(), companyId: z.string().optional(), limit: z.coerce.number().min(1).max(100).default(20), }) crmProxy.get( '/contacts', zValidator('query', ContactQuerySchema), async (c) => { const query = c.req.valid('query') const cacheKey = `contacts:${JSON.stringify(query)}` // 1. キャッシュチェック(プラットフォーム別のKV実装) const cached = await c.env.KV.get(cacheKey) if (cached) { return c.json(JSON.parse(cached)) } // 2. HubSpot API呼び出し const hubspotResponse = await fetch( `https://api.hubapi.com/crm/v3/objects/contacts?limit=${query.limit}`, { headers: { Authorization: `Bearer ${c.env.HUBSPOT_ACCESS_TOKEN}`, 'Content-Type': 'application/json', }, } ) if (!hubspotResponse.ok) { const errorBody = await hubspotResponse.text() throw new Error(`HubSpot API error: ${hubspotResponse.status} ${errorBody}`) } const hubspotData = await hubspotResponse.json() // 3. スキーマ変換(HubSpot固有 → 統一フォーマット) const contacts = hubspotData.results.map((contact: HubSpotContact) => ({ id: contact.id, email: contact.properties.email, company: contact.properties.company, aiScore: Number(contact.properties.ai_score) || 0, lifecycleStage: contact.properties.lifecyclestage, lastEnrichedAt: contact.properties.last_enriched_at, })) const result = { contacts, total: hubspotData.total, paging: hubspotData.paging, } // 4. キャッシュ保存(TTL: 5分) await c.env.KV.put(cacheKey, JSON.stringify(result), { expirationTtl: 300 }) return c.json(result) } ) export { crmProxy }

プラットフォーム別エントリポイント

Cloudflare Workers

typescript
// src/index.ts (Cloudflare Workers) import { Hono } from 'hono' import { crmProxy } from './routes/crm-proxy' type Bindings = { KV: KVNamespace HUBSPOT_ACCESS_TOKEN: string } const app = new Hono<{ Bindings: Bindings }>() app.route('/api/crm', crmProxy) export default app
toml
# wrangler.toml name = "gtm-crm-proxy" main = "src/index.ts" compatibility_date = "2026-04-01" [[kv_namespaces]] binding = "KV" id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" [vars] HUBSPOT_ACCESS_TOKEN = ""

AWS Lambda

typescript
// src/index.ts (AWS Lambda) import { Hono } from 'hono' import { handle } from 'hono/aws-lambda' import { crmProxy } from './routes/crm-proxy' const app = new Hono() app.route('/api/crm', crmProxy) export const handler = handle(app)
yaml
# serverless.yml service: gtm-crm-proxy provider: name: aws runtime: nodejs20.x region: ap-northeast-1 memorySize: 256 timeout: 30 environment: HUBSPOT_ACCESS_TOKEN: ${ssm:/gtm/hubspot-access-token} functions: api: handler: dist/index.handler events: - httpApi: '*'

Vercel

typescript
// app/api/crm/[...path]/route.ts (Vercel Edge Functions) import { Hono } from 'hono' import { handle } from 'hono/vercel' import { crmProxy } from '@/lib/routes/crm-proxy' export const runtime = 'edge' const app = new Hono().basePath('/api/crm') app.route('/', crmProxy) export const GET = handle(app) export const POST = handle(app)
json
// vercel.json { "regions": ["hnd1"], "functions": { "app/api/**": { "memory": 256, "maxDuration": 30 } } }

レイテンシ計測結果

CRM API中継シナリオ(10,000リクエスト、HubSpot API応答時間を除いたプロキシ層のオーバーヘッド)。

メトリクスCloudflare WorkersAWS LambdaVercel Edge
p503ms12ms5ms
p958ms45ms14ms
p9915ms180ms(コールドスタート含む)22ms
コールドスタートなし150-300msなし

Cloudflare Workersのp50が3msなのは、V8 isolateのウォームアップが不要なためだ。AWS Lambdaのp99が180msに跳ね上がるのはコールドスタートの影響。VPC内にLambdaを配置している場合、ENI(Elastic Network Interface)のアタッチでさらに1-2秒加算される。

GTMエンジニアリングの文脈では、CRM API中継のレイテンシは「営業が画面でストレスを感じるか」で判断する。p95で50ms以下なら営業は気にしない。3プラットフォームとも実用上は十分だが、Cloudflare Workersのエッジ分散はダッシュボードのリクエストが多い場面で体感差が出る。

月間コスト比較

CRM API中継シナリオの月間コスト。為替は1ドル=150円。

リクエスト数/月Cloudflare WorkersAWS LambdaVercel
10万$0(Free枠内)$0.20$0(Hobby枠内)
100万$5$2.10$20(Pro最低額)
1,000万$5$21.00$20 + 従量

Cloudflare Workers Paidプランは$5/月で1,000万リクエストを含む。この価格帯ではCloudflare Workersのコスト効率が群を抜く。AWS Lambdaは従量課金が線形に増えるが、月間100万リクエスト程度では微差。Vercelは最低月額$20(Pro)が固定でかかる。

シナリオ2: AIパイプライン処理

ユースケース

前回記事で構築した、Claude APIを呼び出してリードを分析するパイプラインのインフラ比較。リードデータを受け取り、Claude APIで課題仮説を生成し、結果をCRMに書き戻す処理だ。

このシナリオで重要になるのは実行時間制限だ。Claude APIの応答は入力トークン数に依存し、企業リサーチのプロンプトでは5-30秒かかることがある。

共通ビジネスロジック

typescript
// src/routes/ai-pipeline.ts -- 3プラットフォーム共通 import { Hono } from 'hono' import { z } from 'zod' import Anthropic from '@anthropic-ai/sdk' const aiPipeline = new Hono() const LeadAnalysisSchema = z.object({ companyName: z.string(), companyUrl: z.string().url(), industry: z.string(), employeeCount: z.number(), recentNews: z.array(z.string()).default([]), techStack: z.array(z.string()).default([]), }) aiPipeline.post('/analyze-lead', async (c) => { const lead = await c.req.json() const validated = LeadAnalysisSchema.parse(lead) const anthropic = new Anthropic({ apiKey: c.env.ANTHROPIC_API_KEY, }) // Claude APIでリード分析 const message = await anthropic.messages.create({ model: 'claude-sonnet-4-5-20250514', max_tokens: 2048, messages: [{ role: 'user', content: `以下の企業情報を分析し、JSON形式で出力してください。 企業名: ${validated.companyName} 業種: ${validated.industry} 従業員数: ${validated.employeeCount} 直近ニュース: ${validated.recentNews.join('\n')} 技術スタック: ${validated.techStack.join(', ')} 出力形式: { "score": 0-100の適合度スコア, "challenges": ["推定される経営課題1", "課題2", "課題3"], "triggerEvent": "アプローチのきっかけとなるイベント", "proposedApproach": "提案の方向性", "confidence": 0-1の確信度 }` }], }) const analysisText = message.content[0].type === 'text' ? message.content[0].text : '' const analysis = JSON.parse(analysisText) // CRMに書き戻し await updateCrmContact(c.env.HUBSPOT_ACCESS_TOKEN, validated.companyName, { ai_score: String(analysis.score), ai_hypothesis: analysis.challenges.join(' / '), ai_trigger_event: analysis.triggerEvent, ai_proposed_approach: analysis.proposedApproach, }) return c.json({ company: validated.companyName, analysis, processedAt: new Date().toISOString(), }) }) export { aiPipeline }

実行時間制限の比較

AIパイプライン処理で最も重要な制約は実行時間の上限だ。

プラットフォームプラン最大実行時間AIパイプラインへの影響
Cloudflare WorkersFree10ms CPU時間(ただしI/O待ちは別カウント)fetch待ちはCPU時間に含まれないため、Claude APIの応答待ちは問題ない
Cloudflare WorkersPaid ($5/月)30秒 CPU時間通常のリード分析は十分
Cloudflare WorkersPaid + Cron Trigger15分バッチ処理も対応可能
AWS Lambda全プラン15分制約なし
VercelHobby10秒Claude APIの応答が間に合わないケースがある
VercelPro (Edge)60秒通常のリード分析は十分
VercelPro (Serverless)300秒バッチ処理も対応可能

Cloudflare Workersの「CPU時間」と「ウォールクロック時間」の区別は重要だ。fetch()によるI/O待ち(Claude APIの応答待ちを含む)はCPU時間にカウントされない。したがって、Freeプランの10ms CPU時間制限でも、Claude APIを呼び出すパイプラインは動作する。ただし、JSON.parseやデータ変換などの純粋なCPU処理が10msを超えると制限に抵触する。

ストリーミングレスポンスの対応状況

リアルタイムで営業ダッシュボードにAI分析結果を表示する場合、ストリーミングレスポンスが必要になる。

typescript
// ストリーミング対応の実装例(Cloudflare Workers / Hono) aiPipeline.post('/analyze-lead/stream', async (c) => { const lead = await c.req.json() const validated = LeadAnalysisSchema.parse(lead) const anthropic = new Anthropic({ apiKey: c.env.ANTHROPIC_API_KEY, }) const stream = await anthropic.messages.stream({ model: 'claude-sonnet-4-5-20250514', max_tokens: 2048, messages: [{ role: 'user', content: `${validated.companyName}の企業分析を行ってください。...` }], }) return new Response(stream.toReadableStream(), { headers: { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }, }) })
機能Cloudflare WorkersAWS LambdaVercel Edge
ReadableStream対応対応(Function URL / Response Streaming)対応
Server-Sent Events対応対応対応
WebSocketDurable Objects経由で対応API Gateway WebSocket非対応(外部サービス推奨)

3プラットフォームとも基本的なストリーミングには対応している。AWS Lambdaのストリーミング対応は2023年から利用可能で、Function URLを経由すれば追加設定なしで使える。

バッチ処理 vs リアルタイム処理

GTMエンジニアリングのAIパイプラインでは、リアルタイム処理とバッチ処理を使い分ける。

リアルタイム処理(1件ずつ): 新規リード登録時に即座に分析。営業に5分以内で通知したい場合。

バッチ処理(まとめて): 毎朝8時に前日の未分析リードを一括処理。コスト効率を優先する場合。

処理方式推奨プラットフォーム理由
リアルタイム(1件)Cloudflare Workersコールドスタートなし、エッジ分散で即応
バッチ(100件以下)AWS Lambda15分の実行時間、SQSキューとの統合
バッチ(100件以上)AWS Lambda + Step FunctionsStep Functionsで並列実行を制御
ストリーミング表示Cloudflare Workers or Vercel EdgeSSE/ReadableStreamが手軽に使える

AIパイプラインの計測結果

リード1件あたりの処理時間(Claude API応答時間を含む)。

メトリクスCloudflare WorkersAWS LambdaVercel Edge
p504.2秒4.5秒4.3秒
p958.1秒9.2秒8.4秒
p9912.3秒14.8秒12.9秒

処理時間の大半はClaude APIの応答待ちだ。プラットフォーム間の差は1秒未満で、AIパイプラインではインフラの差が出にくい。差が出るのはコールドスタート時のAWS Lambda(p99で+2秒程度)と、実行時間制限に近づく長いプロンプトを処理する場合だ。

シナリオ3: Webhook受信

ユースケース

HubSpotの「コンタクト作成」「商談ステージ変更」などのイベントをWebhookで受信し、後続処理をトリガーする。GTMエンジニアリングのイベント駆動アーキテクチャの起点となるワークロードだ。

Webhook受信の技術要件は3つ。

  1. 即応性: Webhook送信元はタイムアウトが短い(HubSpotは5秒)。受信確認を即座に返す必要がある
  2. 同時実行耐性: CRMで一括操作が行われると、短時間に数百のWebhookが飛んでくる
  3. 署名検証: 改ざん防止のための署名検証が必須

共通ビジネスロジック

typescript
// src/routes/webhook.ts -- 3プラットフォーム共通 import { Hono } from 'hono' import { createHmac } from 'node:crypto' const webhook = new Hono() // HubSpot Webhook署名検証ミドルウェア async function verifyHubSpotSignature( body: string, signature: string, secret: string ): Promise<boolean> { const hash = createHmac('sha256', secret) .update(body) .digest('hex') return hash === signature } webhook.post('/hubspot', async (c) => { const body = await c.req.text() const signature = c.req.header('X-HubSpot-Signature-v3') ?? '' // 1. 署名検証 const isValid = await verifyHubSpotSignature( body, signature, c.env.HUBSPOT_WEBHOOK_SECRET ) if (!isValid) { return c.json({ error: 'Invalid signature' }, 401) } // 2. 即座にACK返却(後続処理は非同期) const events = JSON.parse(body) // 3. 非同期で後続処理をキューに投入 for (const event of events) { await c.env.QUEUE.send({ type: event.subscriptionType, objectId: event.objectId, propertyName: event.propertyName, propertyValue: event.propertyValue, occurredAt: event.occurredAt, }) } return c.json({ received: events.length }, 200) }) export { webhook }

署名検証の実装差異

Webhook受信のセキュリティで注意すべきは、Cloudflare WorkersのランタイムがNode.jsではなくV8 isolateである点だ。node:cryptoの一部がWorkers環境で利用できない場合がある。

typescript
// Cloudflare Workers向け: Web Crypto APIを使った署名検証 async function verifyHubSpotSignatureWorkers( body: string, signature: string, secret: string ): Promise<boolean> { const encoder = new TextEncoder() const key = await crypto.subtle.importKey( 'raw', encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'] ) const sig = await crypto.subtle.sign( 'HMAC', key, encoder.encode(body) ) const hashHex = Array.from(new Uint8Array(sig)) .map(b => b.toString(16).padStart(2, '0')) .join('') return hashHex === signature }
暗号化APICloudflare WorkersAWS LambdaVercel EdgeVercel Serverless
node:crypto一部対応(2026年時点で改善中)完全対応非対応完全対応
Web Crypto API完全対応完全対応完全対応完全対応

結論として、Web Crypto APIを使えば3プラットフォーム共通のコードが書ける。node:cryptoに依存するライブラリを使う場合はEdge環境での互換性を確認する必要がある。

同時実行数の比較

CRMの一括更新操作で500件のWebhookが同時に飛んでくるケースの挙動。

プラットフォーム同時実行上限スケーリング速度影響
Cloudflare Workers事実上無制限(グローバルエッジ分散)即座500件同時でも問題なし
AWS Lambda1,000(デフォルト、引き上げ申請可)500/分でスケールアップ初回は500件同時で一部がスロットリング。予約済み同時実行数を設定すれば回避
Vercel1,000(Pro)即座500件同時でも問題なし

AWS Lambdaのスケーリングにはバーストリミットがある。東京リージョンでは初回バーストが500で、以降は500/分でスケールアップする。GTMエンジニアリングの通常ワークロードでは問題にならないが、データ移行時の大量Webhook発火には注意が必要だ。

リトライとデッドレターキュー

Webhook処理が失敗した場合の再試行設計。

Cloudflare Workers + Queues

toml
# wrangler.toml [[queues.producers]] binding = "QUEUE" queue = "gtm-webhook-queue" [[queues.consumers]] queue = "gtm-webhook-queue" max_batch_size = 10 max_retries = 3 dead_letter_queue = "gtm-webhook-dlq"

AWS Lambda + SQS

yaml
# serverless.yml functions: webhookProcessor: handler: dist/webhook-processor.handler events: - sqs: arn: !GetAtt WebhookQueue.Arn batchSize: 10 deadLetterTargetArn: !GetAtt WebhookDLQ.Arn resources: Resources: WebhookQueue: Type: AWS::SQS::Queue Properties: VisibilityTimeout: 60 RedrivePolicy: deadLetterTargetArn: !GetAtt WebhookDLQ.Arn maxReceiveCount: 3 WebhookDLQ: Type: AWS::SQS::Queue

Vercel

Vercelにはネイティブのキューイングサービスがない。Webhook受信後の非同期処理には外部キュー(Upstash QStash、AWS SQS等)との統合が必要。

機能Cloudflare WorkersAWS LambdaVercel
ネイティブキューQueuesSQSなし(外部サービス要)
DLQ対応対応外部サービス依存
リトライ設定max_retries指定SQS RedrivePolicy外部サービス依存
バッチ処理max_batch_size指定batchSize指定外部サービス依存

Webhook受信の信頼性設計では、AWS LambdaとSQSの組み合わせが最も成熟している。Cloudflare Queuesは2023年にGAとなり急速に改善されているが、SQSの10年以上の運用実績には及ばない。Vercelは外部キューに依存するため、Webhook中心のアーキテクチャには不向きだ。

DX(Developer Experience)比較

GTMエンジニアは少人数(多くの場合1-3名)で運用する。開発体験の良し悪しは生産性に直結する。

ローカル開発

項目Cloudflare WorkersAWS LambdaVercel
ローカル実行wrangler dev(高速、ホットリロード)sam local invoke / serverless offlinevercel dev(Next.js統合)
起動時間1-2秒5-15秒(Docker起動含む)3-5秒
本番互換性高い(同一V8ランタイム)中(Dockerコンテナでエミュレート)高い(Edge Runtime再現)
環境変数.dev.varsファイルenv.json / --env-vars.env.local

wrangler devの起動が1-2秒なのは、V8 isolateの軽量さによる。AWS Lambdaのローカル実行はDockerコンテナベースで起動に時間がかかるが、serverless-offlineプラグインを使えばDocker不要で軽量に動作する。Vercelはnext devと統合されており、フロントエンドと同時に開発する場合の体験が良い。

デプロイ速度

同一のHonoアプリケーションをデプロイした際の所要時間。

メトリクスCloudflare WorkersAWS LambdaVercel
初回デプロイ5秒30-60秒15-30秒
更新デプロイ2-3秒15-30秒10-15秒
ロールバック即座(バージョン管理)30秒(CloudFormation)即座(デプロイメント切り替え)
bash
# Cloudflare Workers: デプロイコマンド wrangler deploy # 2-3秒で完了 # AWS Lambda (Serverless Framework): デプロイコマンド serverless deploy # CloudFormationスタック更新で30秒以上 # Vercel: デプロイコマンド(git push でも自動デプロイ) vercel --prod # ビルド + デプロイで10-15秒

Cloudflare Workersのデプロイ速度はイテレーション速度に直結する。GTMエンジニアリングでは「営業チームからの要望を受けて即座に修正デプロイする」場面が多い。2-3秒でデプロイが完了する体験は、開発サイクルの速さそのものだ。

ログとデバッグ

項目Cloudflare WorkersAWS LambdaVercel
リアルタイムログwrangler tailCloudWatch LogsVercel Logs(ダッシュボード)
ログ保持期間無料枠なし(Logpush推奨)永続(CloudWatch課金)1時間(Hobby)/ 3日(Pro)
構造化ログJSON出力対応JSON出力対応JSON出力対応
トレーシングWorkers Analytics EngineX-Ray基本的な分析のみ
エラー追跡Sentry統合Sentry / CloudWatch AlarmsSentry統合

ログ基盤はAWS Lambdaが最も充実している。CloudWatch Logsの検索、メトリクスフィルター、アラーム設定は成熟しており、本番運用で信頼できる。Cloudflare Workersのログはwrangler tailでリアルタイム閲覧できるが、永続保存にはLogpush(R2, S3等への転送)の設定が必要。Vercelのログ保持期間が短い点は、障害調査時に制約になる。

CI/CD統合

項目Cloudflare WorkersAWS LambdaVercel
GitHub Actionscloudflare/wrangler-actionserverless/github-actionamondnet/vercel-action
プレビュー環境Branch deploymentsステージ分離PRごとのプレビューURL
テスト統合Vitest + MiniflareJest / VitestJest / Vitest

VercelのPRごとのプレビュー環境は、営業チームにデモを見せる場面で有用だ。「この修正のプレビューURLを営業に共有して確認してもらう」というワークフローが標準で組み込まれている。

コスト詳細比較

GTMエンジニアリングの3シナリオを統合した月間コスト比較。CRM API中継(全体の70%)+ AIパイプライン(20%)+ Webhook受信(10%)の構成比を想定。

月間10万リクエスト(スタートアップ / 営業5名規模)

項目Cloudflare WorkersAWS LambdaVercel
コンピュート$0(Free枠内)$0.21$0(Hobby枠内)
ストレージ(KV/S3等)$0(Free枠内)$0.50$0
帯域$0$0.10$0
合計$0$0.81(約120円)$0

推奨: Cloudflare Workers。月間10万リクエストは無料枠で完全に収まる。Vercel Hobbyプランでも無料だが、商用利用にはProプラン($20/月)が推奨される規約がある。

月間100万リクエスト(Mid Market / 営業15名規模)

項目Cloudflare WorkersAWS LambdaVercel
コンピュート$5$4.18$20(Pro最低額)
ストレージ$0(KV無料枠内)$5.00$0(KV無料枠内)
キュー/SQS$0(Queues無料枠内)$0.40$5(外部キュー)
帯域$0$1.00$0(100GB枠内)
合計$5(約750円)$10.58(約1,590円)$25(約3,750円)

推奨: Cloudflare Workers。$5/月でキュー、KV、コンピュートが全て含まれる。AWS Lambdaは個別サービスの積み上げで$10を超える。Vercelは最低$20の固定費が支配的。

月間1,000万リクエスト(エンタープライズ / 営業50名規模)

項目Cloudflare WorkersAWS LambdaVercel
コンピュート$5$41.80$20 + $36(超過分)
ストレージ$5(KV有料帯)$25.00$10
キュー/SQS$2$4.00$20(外部キュー)
帯域$0$10.00$40(帯域超過)
追加サービス(Durable Objects等)$10$15(Step Functions等)$15
合計$22(約3,300円)$95.80(約14,370円)$141(約21,150円)

推奨: Cloudflare Workers。ただし、VPC内にデータを閉じる要件がある場合はAWS Lambda一択。Cloudflare Workersはエッジ分散のため、データの所在地を厳密に制御する用途には追加の設計(Jurisdiction APIの利用)が必要。

月間1億リクエスト(大規模GTMプラットフォーム)

項目Cloudflare WorkersAWS LambdaVercel
合計$55-100$850-1,200$1,500+

この規模ではCloudflare Workersのコスト効率が圧倒的になる。1,000万リクエスト込みの$5基本料金に対し、超過分は100万リクエストあたり$0.50。AWS Lambdaの100万リクエストあたり$0.20 + 実行時間課金の合計よりも安い。

コストの支配的要因をリクエスト数別にまとめると:

10万リクエスト/月:  → 差は無視できる。全プラットフォーム無料〜$5以内
100万リクエスト/月: → 固定費の差が支配的。CF Workers $5 vs Vercel $20
1,000万リクエスト/月: → 従量課金の差が顕在化。CF Workers $22 vs Lambda $96
1億リクエスト/月:   → CF Workersの包含モデルが圧勝。$55 vs $850

GTMエンジニアへの推奨

まず始めるならCloudflare Workers

GTMエンジニアリングを始める際の第一選択はCloudflare Workersだと思う。

  • 無料枠が大きい(10万リクエスト/日、KV 1GB、R2 10GB)
  • コールドスタートなし(営業ダッシュボードの体感速度が良い)
  • HonoとのネイティブなTypeScript統合
  • デプロイが2-3秒(営業からの要望に即座に対応できる)
  • Queues、D1、Durable Objectsなどエコシステムが充実

技術選定フレームワークで述べたスタートアップのパターンAそのものだ。

bash
# Cloudflare Workers + Hono で即座に始める npm create hono@latest gtm-api -- --template cloudflare-workers cd gtm-api wrangler dev # 2秒でローカル起動 # コード編集... wrangler deploy # 3秒で本番デプロイ

エンタープライズ顧客がいるならAWS Lambda

エンタープライズ向けBtoB SaaSを展開している場合、AWS Lambdaを選ぶ理由が明確になる。

  • VPC内にデータを閉じられる(セキュリティ要件)
  • 既存AWSインフラ(RDS、S3、SQS)との統合が容易
  • IAMによるきめ細かいアクセス制御
  • Amazon Bedrock経由でClaude APIをVPC内から呼べる
  • SOC 2、ISO 27001等のコンプライアンス対応が容易
yaml
# AWS Lambda + Hono: VPC内で完結するGTMパイプライン provider: name: aws runtime: nodejs20.x region: ap-northeast-1 vpc: securityGroupIds: - sg-xxxxxxxx subnetIds: - subnet-xxxxxxxx - subnet-yyyyyyyy iamRoleStatements: - Effect: Allow Action: - bedrock:InvokeModel - sqs:SendMessage - s3:PutObject Resource: '*'

技術選定フレームワークのパターンC(エンタープライズ向け)に対応する。

フロントエンド込みならVercel

営業ダッシュボードをNext.jsで構築し、同一プロジェクトでAPIも管理する場合、Vercelの統合体験が光る。

  • Next.js App Router + Server Components + Edge Functions が1つのプロジェクトで完結
  • PRごとのプレビュー環境で営業チームに変更を見せやすい
  • Vercel Analytics / Speed Insights でダッシュボードのパフォーマンス監視
  • vercel.json1ファイルで設定完結
json
// vercel.json: Next.js + API が1プロジェクトで完結 { "framework": "nextjs", "regions": ["hnd1"], "crons": [ { "path": "/api/cron/daily-enrichment", "schedule": "0 23 * * 1-5" } ] }

複数プラットフォーム併用の実例

実際のGTMエンジニアリングでは、単一プラットフォームで完結しないケースが多い。

実運用の構成例:

┌─ Cloudflare Workers ─────────────────────────────┐
│  CRM API中継 / Webhook受信 / エッジキャッシュ      │
│  → 低レイテンシ・高頻度の処理はエッジで処理        │
└──────────────────────────┬────────────────────────┘
                           │ キューイング
                           ↓
┌─ AWS Lambda ─────────────────────────────────────┐
│  AIパイプライン処理 / バッチ処理 / VPC内処理       │
│  → 長時間実行・セキュリティ要件のある処理はAWSで   │
└──────────────────────────┬────────────────────────┘
                           │ データ連携
                           ↓
┌─ Vercel ─────────────────────────────────────────┐
│  営業ダッシュボード (Next.js) / 社内管理画面       │
│  → フロントエンドはVercelのDXを活かす              │
└──────────────────────────────────────────────────┘

この構成のメリットは、各プラットフォームの強みだけを使っている点だ。Honoをフレームワークとして共通化しているため、ビジネスロジックは3プラットフォームで共有でき、エントリポイントだけが異なる。

コストもこの構成で最適化される。高頻度のAPI中継はCloudflare Workersの$5/月で処理し、AI処理やバッチはAWS Lambdaの従量課金で使った分だけ払い、ダッシュボードはVercel Proの$20/月で運用する。月間100万リクエスト規模で合計$35/月程度に収まる。


Phase 1として4本書いてきた記事を振り返ると、GTMエンジニアリングのインフラ選定は正直シンプルで、最初はCloudflare Workers + Honoで始めて、必要に応じてAWSとVercelを足していく形が現実的だと思う。複数プラットフォームの並列比較をやってみて改めて感じたのは、インフラよりもプロンプト設計やCRMのデータモデル設計の方が差が出る部分だということだ。

Phase 2では実践編に入る。最初のテーマはカスタムデモ環境の構築 -- 営業商談のクロージング率を上げるために、顧客データに最適化されたデモ環境をGTMエンジニアがどう設計・実装するかを書く予定だ。


参考資料

$ echo $TAGS
#Cloudflare Workers#AWS Lambda#Vercel#Hono#ベンチマーク#コスト比較