Edge Computing 実務設計パターン

Edge Computing をWeb開発の実務でどう使うか。インフラ論ではなく「リクエストが到着してからレスポンスを返すまでに Edge で何をするか」の設計パターン集。

1. Edge Middleware パターン

Edge Middleware とは

リクエストがオリジンに到達する前に、Edge PoP 上で実行される軽量な介入コード。リクエスト/レスポンスの検査・加工・ルーティング判断を行い、不要なリクエストをオリジンに流さない「門番」の役割を担う。

graph LR
    Client["Client"] --> Edge{"Edge Middleware<br/>(V8 Isolate)"}
    Edge -->|"Pass"| Origin["Origin Server"]
    Edge -->|"Reject / Redirect / Rewrite"| Client
    Origin --> Edge
    Edge -->|"Header 注入 / レスポンス加工"| Client

従来のオリジン側ミドルウェア (Express middleware 等) との決定的違い:

Next.js Middleware

プロジェクトルートの middleware.ts に配置。Vercel Edge Functions 上でグローバル実行。

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  // 1. 認証チェック
  const token = request.cookies.get('session')?.value
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  // 2. Rewrite (URL を内部的に書き換え、ブラウザの URL は変わらない)
  if (request.nextUrl.pathname === '/blog') {
    return NextResponse.rewrite(new URL('/blog/home', request.url))
  }

  // 3. ヘッダ注入
  const response = NextResponse.next()
  response.headers.set('X-Frame-Options', 'DENY')
  response.headers.set('X-Content-Type-Options', 'nosniff')
  return response
}

// matcher: Middleware を実行するパスを静的に定義
// 値は定数でなければならない (ビルド時に静的解析される)
export const config = {
  matcher: [
    '/dashboard/:path*',
    '/api/:path*',
    '/((?!_next/static|_next/image|favicon.ico).*)',
  ],
}

matcher のベストプラクティス: 可能な限り具体的に定義する。全パスで実行すると不要なオーバーヘッドが発生する。negative lookahead で静的アセットを除外するのが定石。

CVE-2025-29927: Next.js Middleware バイパス脆弱性。x-middleware-subrequest ヘッダを外部から注入することで Middleware を迂回できた。教訓: Middleware を唯一の認証レイヤーにしてはならない。Data Access Layer パターンで多層防御を実現すべき。

Cloudflare Workers を Middleware として使う

Workers はスタンドアロンの Edge 実行環境だが、既存オリジンの前段に配置して Middleware として機能させるパターンが多い。

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url)

    // 地理的ルーティング
    const country = request.cf?.country || 'US'
    if (country === 'JP') {
      url.hostname = 'api-tokyo.example.com'
    } else if (country === 'DE') {
      url.hostname = 'api-frankfurt.example.com'
    }

    // オリジンにプロキシ
    const response = await fetch(url.toString(), request)

    // セキュリティヘッダ注入
    const modifiedResponse = new Response(response.body, response)
    modifiedResponse.headers.set('Strict-Transport-Security', 'max-age=31536000')
    modifiedResponse.headers.set('X-Content-Type-Options', 'nosniff')
    return modifiedResponse
  }
}

認証 at the Edge

JWT 検証を Edge で実行し、不正なリクエストをオリジンに到達させない。Web Crypto API で署名検証が可能。

async function verifyJWT(token: string, secret: CryptoKey): Promise<boolean> {
  const [headerB64, payloadB64, signatureB64] = token.split('.')
  const data = new TextEncoder().encode(`${headerB64}.${payloadB64}`)
  const signature = base64UrlDecode(signatureB64)
  return crypto.subtle.verify('HMAC', secret, signature, data)
}

Clerk の実装例: ハイブリッド JWT アプローチで認証を 1ms 未満で実行。セッション失効は1分以内にグローバル伝播。

制約: Edge での認証はステートレス検証 (JWT の署名検証、有効期限チェック) に限定すべき。セッション DB へのルックアップはレイテンシが発生するため、KV にキャッシュするか Edge Config を使う。

Rate Limiting at the Edge

2つのアプローチ:

手法一貫性精度コスト
Workers KV + カウンターEventual (~60秒)近似的低い
Durable ObjectsStrong正確高い

KV 方式は PoP ごとにカウンターが分散するため厳密なレート制限は不可能だが、大半のユースケースには十分。厳密な制御が必要なら Durable Objects (API キーごとに1 DO インスタンス) を使う。

Cloudflare の Rate Limiting binding: スライディングウィンドウ方式の組み込みレート制限。Worker のコードに直接統合可能。

Bot 検出 at the Edge

Cloudflare Bot Management: ML + 行動分析で Bot Score (1-99) を算出。Score < 30 は Bot の可能性が高い。

export default {
  async fetch(request: Request): Promise<Response> {
    const botScore = request.cf?.botManagement?.score || 0
    if (botScore < 30) {
      return new Response('Blocked', { status: 403 })
    }
    // 正常なリクエストはオリジンへ
    return fetch(request)
  }
}

Detection IDs (cf.bot_management.detection_ids) で検出ロジックの種類を識別可能。WAF カスタムルール、Rate Limiting ルール、Workers で横断的にアクセス可能。

地理的ルーティング

request.cf.country, request.cf.city, request.cf.region 等で判定。

ユースケース: リージョナルオリジンへの振り分け、法規制対応 (GDPR 圏の PII 処理制限)、通貨・言語のデフォルト設定。

A/B テスト at the Edge

Edge は A/B テストの「キラーアプリ」。クライアントサイドの A/B テストで発生するフリッカー (元のコンテンツが一瞬見えてから変わる) を完全に排除できる。

export function middleware(request: NextRequest) {
  // 既存の Cookie があればそれを使う (セッション維持)
  const variant = request.cookies.get('ab-variant')?.value
    || (Math.random() < 0.5 ? 'A' : 'B')

  const response = NextResponse.rewrite(
    new URL(`/experiment/${variant}`, request.url)
  )
  // Cookie がなければ設定 (次回以降同じバリアントを表示)
  if (!request.cookies.has('ab-variant')) {
    response.cookies.set('ab-variant', variant, { maxAge: 60 * 60 * 24 * 30 })
  }
  return response
}

決定論的ハッシュ (ユーザー ID をキーに) で割り当てると、Cookie 不要でも一貫したバリアントを保証できる。

Feature Flags at the Edge

Edge での Feature Flag 評価は、SDK がフラグ定義を Edge データストアから読み込み、ネットワーク往復なしで評価するモデル。

プロバイダEdge ストア伝播速度
LaunchDarkly + CloudflareWorkers KV~60秒
LaunchDarkly + VercelEdge Config<300ms
Statsig + VercelEdge Config<300ms
自前実装Workers KV / D1~60秒

LaunchDarkly の Cloudflare 統合: フラグデータを Workers KV に同期。Worker 内で評価する際にネットワーク往復不要。クライアントサイド ID (非秘密) を使用。

Vercel Flags SDK: @flags-sdk/launchdarkly アダプターで LaunchDarkly フラグを Edge Config 経由で同期読み出し。ネットワークホップゼロ。

注意: CDN キャッシュはフラグ更新の遅延を増幅する。頻繁に変更するフラグには Edge Config (<300ms 伝播) が適し、KV (最大60秒) は安定したフラグ向き。

ヘッダ操作

セキュリティヘッダ注入はオリジンの責務から Edge に移すべき最も手軽で効果的なパターン。

const SECURITY_HEADERS = {
  'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
  'X-Content-Type-Options': 'nosniff',
  'X-Frame-Options': 'DENY',
  'Referrer-Policy': 'strict-origin-when-cross-origin',
  'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
}

// CORS ヘッダも Edge で統一管理
const CORS_HEADERS = {
  'Access-Control-Allow-Origin': 'https://example.com',
  'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}

2. Edge-Side Rendering (ESR) / Edge SSR

Origin SSR vs Edge SSR

特性Origin SSREdge SSR
実行場所中央データセンター (1-3箇所)CDN PoP (300+ 箇所)
TTFB50-300ms (地理距離に依存)10-50ms (ユーザーに近い)
Cold start数百ms-数秒 (コンテナ/Lambda)<1ms (V8 Isolate)
Node.js APIフルアクセス制限あり (Edge Runtime)
データアクセスDB 直接接続HTTP/WS 経由、KV/D1
CPU 制限緩い厳格 (10-50ms CPU 時間)

Edge SSR のメリットは「全世界のユーザーに対して均一に低い TTFB を提供」すること。Origin SSR ではオリジンに近いユーザーのみ高速だが、Edge SSR は地理的不公平を解消する。

Streaming SSR at the Edge

React 18 の renderToReadableStream (Web Streams API) が Edge Runtime で使用可能。

// Edge Runtime で Streaming SSR
export const runtime = 'edge'

export default async function handler(req: Request) {
  const stream = await renderToReadableStream(<App />, {
    bootstrapScripts: ['/client.js'],
  })
  return new Response(stream, {
    headers: { 'Content-Type': 'text/html' },
  })
}

Node.js の renderToPipeableStream に対し、Edge では Web Streams ベースの renderToReadableStream を使う。

Streaming のメリット: ページ全体の描画を待たず、準備できた部分から HTML をストリーミング送信。Suspense 境界で段階的にコンテンツを表示。TTFB と FCP を劇的に改善。

ISR の Edge バリアント

ISR (Incremental Static Regeneration) は stale-while-revalidate パターンの SSG 版。Edge Runtime と ISR は現時点で直接的な互換性がない。

代替パターン: Cache-Control ヘッダを手動設定。

Cache-Control: public, s-maxage=60, stale-while-revalidate=3600

Next.js 15.2 の ISR + revalidate は Vercel CDN 上で stale-while-revalidate を実現。Edge Runtime の再生成オーバーヘッドを 70% 削減。

React Server Components と Edge

RSC は Edge SSR との親和性が高い。

// app/page.tsx — Edge で RSC を実行
export const runtime = 'edge'

export default async function Page() {
  // Edge PoP 上でデータ取得
  const data = await fetch('https://api.example.com/products', {
    next: { revalidate: 60 },
  })
  const products = await data.json()
  return <ProductList products={products} />
}

制約: RSC が Edge で呼び出す外部 API が地理的に遠い場合、Edge 化のメリットが薄れる。データソースの位置と Edge の位置関係を意識する必要がある (Data Gravity)。

Next.js Edge Runtime

export const runtime = 'edge' で Page / Route Handler を Edge Runtime に切り替え。

Node.js RuntimeEdge Runtime
APIフル Node.jsWeb API サブセット
ファイル I/Oありなし
DB 接続TCP 直接HTTP/WS 経由
npm パッケージほぼ全てNode.js 依存パッケージは不可
バンドルサイズ制限緩い厳格 (数 MB)
Cold start数百ms<1ms

フレームワーク Edge 対応状況 (2026)

フレームワークEdge SSREdge MiddlewareEdge API備考
Next.jsruntime = 'edge'middleware.tsRoute Handler最も成熟。Vercel 統合
SvelteKitNetlify Edge Adapter--edge: true オプション。Deno Deploy 対応
NuxtNitro + Edge preset-Edge API routesCloudflare Workers, Deno Deploy
RemixCloudflare Workers adapter-Loader/ActionWorkers 上でフル SSR
AstroCloudflare adapter-Edge endpointsハイブリッド (静的 + 動的)

SvelteKit の特徴: 「ビルド一回、どこでもデプロイ」。Node, Serverless, Edge, 静的のいずれにもコード変更なしで対応。

3. Edge でのパーソナライズ

パーソナライズとキャッシュのジレンマ

パーソナライズされたコンテンツは本質的にキャッシュ不可能 (ユーザーごとに異なる)。しかし Edge の価値はキャッシュによる高速化。この矛盾の解決パターンが3つある。

パターン 1: Edge Side Includes (ESI)

ページの静的部分をキャッシュし、動的部分だけを別リクエストで取得して Edge で合成。

<!-- キャッシュ可能なページ -->
<header>共通ナビゲーション</header>
<main>商品一覧 (全ユーザー共通)</main>
<!-- 動的部分: Edge が別途取得して注入 -->
<esi:include src="/api/recommendations?user=123" />
<footer>共通フッター</footer>

ESI (Edge Side Includes) は Akamai が 2001年に提案した W3C Note。現在は Akamai, Fastly (VCL), Cloudflare (Workers で手動実装) がサポート。

Edge Side Rendering (ESR) として、CDN の Edge Computing 機能で静的コンテンツと動的コンテンツをストリーミングモードで段階的に返す進化形もある。

パターン 2: HTML Streaming + Suspense

React の Streaming SSR で、パーソナライズ部分を Suspense 境界内に配置。共通部分を先にストリーミングし、パーソナライズ部分は準備でき次第注入。

export default function Page() {
  return (
    <html>
      <body>
        {/* 即座にストリーミング (キャッシュ可能) */}
        <Header />
        <ProductGrid />
        {/* パーソナライズ部分: 準備でき次第注入 */}
        <Suspense fallback={<Skeleton />}>
          <PersonalizedRecommendations />
        </Suspense>
      </body>
    </html>
  )
}

パターン 3: Edge Middleware での動的ルーティング

事前に複数の静的バリアントを生成し、Edge Middleware でユーザーコンテキストに基づいて適切なバリアントにルーティング。「動的を静的の速度で」。

export function middleware(request: NextRequest) {
  const country = request.geo?.country || 'US'
  const variant = request.cookies.get('pricing-tier')?.value || 'standard'

  // 事前生成済みの静的ページにリライト
  return NextResponse.rewrite(
    new URL(`/pages/${country}/${variant}`, request.url)
  )
}

Geo ベースのパーソナライズ

コンテキストデータソースユースケース
国/地域request.cf.country通貨、法規制対応、コンテンツ制限
都市request.cf.city配送オプション、店舗検索
タイムゾーンrequest.cf.timezone時刻表示、営業時間
言語Accept-Language ヘッダi18n
デバイスUser-Agent / Client Hintsレスポンシブ画像、モバイル最適化

HashiCorp の事例: Edge Middleware で地理情報を使い、ローカライズされたコンテンツ・通貨・言語を即座に提供。外部サービス不要。

4. Edge での画像最適化

Edge 画像最適化パイプライン

graph LR
    Request["画像リクエスト<br/>Accept: image/avif, image/webp"] --> Edge{"Edge PoP"}
    Edge -->|"キャッシュ Hit"| Cached["最適化済み画像<br/>即応答"]
    Edge -->|"キャッシュ Miss"| Transform["リサイズ + フォーマット変換<br/>+ 圧縮"]
    Transform --> Cache["Edge キャッシュに保存"]
    Cache --> Response["最適化済み画像"]

Cloudflare Image Resizing

URL パラメータまたは Workers から変換指示。format=auto で Accept ヘッダに基づき最適フォーマットを自動選択。

/cdn-cgi/image/width=800,quality=80,format=auto/images/photo.jpg
フォーマット圧縮率 (vs JPEG)ブラウザサポートエンコード速度
WebP25-35% 小さい97%+高速
AVIF50%+ 小さい93%+低速 (10x)

AVIF はエンコードが非常に遅いため、Cloudflare ではエンコードが時間内に完了しない場合 WebP にフォールバックする。

Cloudinary / Imgix

Imgix, Cloudinary は専用の Edge CDN で画像変換を実行。URL ベースの変換 API を提供。

// Imgix
https://example.imgix.net/photo.jpg?w=800&auto=format,compress

// Cloudinary
https://res.cloudinary.com/demo/image/upload/w_800,f_auto,q_auto/photo.jpg

Workers AI との統合: AI 生成画像をストレージ前またはデリバリー時に Edge で最適化するパイプラインも構築可能。

5. Edge での API Gateway パターン

Edge API Gateway の構造

graph TB
    Client["Client"] --> Edge{"Edge API Gateway<br/>(Worker)"}
    Edge -->|"認証済み"| Auth["認証 Worker<br/>(Service Binding)"]
    Edge --> RateLimit["Rate Limit<br/>(DO/KV)"]
    Edge --> Cache{"レスポンスキャッシュ"}
    Cache -->|"Hit"| Client
    Cache -->|"Miss"| Backend["Backend Services"]
    Backend --> Cache

リクエストルーティング

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url)

    // パスベースルーティング
    if (url.pathname.startsWith('/api/users')) {
      return env.USERS_SERVICE.fetch(request) // Service Binding
    }
    if (url.pathname.startsWith('/api/products')) {
      return env.PRODUCTS_SERVICE.fetch(request) // Service Binding
    }

    return new Response('Not Found', { status: 404 })
  }
}

Service Binding による Worker-to-Worker 呼び出しは、パブリックインターネットを経由せず、ネットワークホップ・認証オーバーヘッドがゼロ。

認証/認可のオフロード

Edge Gateway で JWT 検証を完了し、認証済みのリクエストだけをバックエンドに転送。バックエンドは認証ロジックを持つ必要がなくなる。

レスポンスキャッシュ

const cacheKey = new Request(request.url, { method: 'GET' })
const cache = caches.default

let response = await cache.match(cacheKey)
if (!response) {
  response = await fetch(request)
  response = new Response(response.body, response)
  response.headers.set('Cache-Control', 's-maxage=60')
  await cache.put(cacheKey, response.clone())
}
return response

BFF (Backend for Frontend) at the Edge

従来の BFF はリージョナルサーバー上に配置していたが、Edge に配置することで:

// Edge BFF: モバイル用に複数 API をまとめる
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const [user, products, notifications] = await Promise.all([
      env.USER_SERVICE.getUser(userId),
      env.PRODUCT_SERVICE.getRecommendations(userId),
      env.NOTIFICATION_SERVICE.getUnread(userId),
    ])

    // モバイルに最適化されたレスポンス
    return Response.json({
      user: { name: user.name, avatar: user.avatar },
      recommendations: products.slice(0, 5),
      unreadCount: notifications.length,
    })
  }
}

注意: BFF がバックエンドを呼び出す際、バックエンドが地理的に遠い場合は Edge 化のメリットが薄れる。Edge → Origin のレイテンシを考慮し、データが Edge にキャッシュ可能かどうかが判断基準。

6. Edge Worker のアーキテクチャパターン

ファンアウト / ファンイン

graph LR
    Req["受信 Worker"] --> Q["Queues"]
    Q --> W1["Consumer Worker 1"]
    Q --> W2["Consumer Worker 2"]
    Q --> W3["Consumer Worker 3"]

Queues で1つのイベントから複数の Consumer を起動するファンアウト。at-least-once delivery、設定可能なリトライ。

ファンインは Service Binding で複数の Worker の結果を1つの Worker で集約:

// 集約 Worker
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const [a, b, c] = await Promise.all([
      env.SERVICE_A.getData(),
      env.SERVICE_B.getData(),
      env.SERVICE_C.getData(),
    ])
    return Response.json({ a, b, c })
  }
}

Service Binding (Worker-to-Worker)

ゼロコスト、ゼロネットワークホップの Worker 間通信。型安全な RPC。

// Worker A が Worker B を呼び出す
const result = await env.AUTH_SERVICE.verifyToken(token)

本質: 各 Worker を独立したマイクロサービスとしてデプロイしつつ、モノリスに匹敵するパフォーマンス特性を維持する。認証、ロギング、Rate Limiting、Feature Flags を個別 Worker に分離し、Service Binding で接続するパターンが推奨。

Queues vs Workflows

QueuesWorkflows
用途単一ステップ、デカップリング多段処理、条件分岐
実行時間短い数時間〜数週間
リトライジョブ全体ステップ単位
一時停止/再開不可可能

組み合わせパターン: 高スループットのエントリポイントで Queues に投入し、各メッセージから Workflow インスタンスを起動。

Edge + Origin ハイブリッドレンダリング

graph TB
    subgraph Edge["Edge 層 (V8 Isolate)"]
        MW["Middleware<br/>認証, ルーティング, A/B"]
        StaticCache["静的アセットキャッシュ"]
        KVRead["KV 読み取り<br/>Feature Flags, 設定"]
    end
    subgraph Origin["Origin 層 (Node.js / Container)"]
        SSR["重い SSR"]
        DB["DB 書き込み"]
        BizLogic["ビジネスロジック"]
    end
    Client --> Edge
    Edge --> Origin
    Origin --> Edge
    Edge --> Client

原則: 読み取り/軽量処理は Edge、書き込み/重い処理は Origin。Edge はオリジンの「スマートなフロントドア」であり、オリジンの代替ではない。

7. アンチパターン

Edge に持っていくべきでないもの

アンチパターン理由
強い一貫性が必要なデータ書き込みACID トランザクション、在庫管理、決済処理は Edge では不可能。Origin DB に任せる
重い計算処理CPU 時間制限 (10-50ms) を超えるとリクエストが 503 で切断される
大きな依存パッケージPDF 生成、重い画像処理ライブラリはバンドルサイズ制限に抵触
外部 API への多段呼び出しEdge → 遠い API × 複数回 = レイテンシ悪化。Data Gravity の法則に反する
秘密情報を含むビジネスロジックEdge は分散実行されるため、セキュリティ表面が広い

Chatty Edge アンチパターン

最も多い設計ミス。Edge にロジックを配置しながら、地理的に遠い DB に繰り返しクエリを発行するパターン。Edge 化のレイテンシ削減効果が相殺され、むしろ悪化する。

// アンチパターン: Edge Worker が遠い DB に5回クエリ
Edge (Tokyo) → DB (Virginia) × 5 = 5 × 200ms = 1,000ms

// 正しい: Origin (Virginia) が DB に5回クエリ
Client → Origin (Virginia) → DB (Virginia) × 5 = 200ms + 5 × 2ms = 210ms

解決策: データが Edge に移動できないなら、コードも移動すべきではない。読み取りレプリカや KV キャッシュで Edge にデータを近づけるか、処理自体を Origin に残す。

過度な Edge 化

全てを Edge に移行しようとする「Edge maximalism」は失敗する。

Worker 固有のアンチパターン

アンチパターン正しいパターン
passThroughOnException() でエラーをオリジンに流す明示的 try-catch + 構造化エラーレスポンス
モジュールレベルの可変状態 (let currentUser)リクエストスコープで状態を渡す。Isolate はリクエスト間で再利用される
浮遊 Promise (await/return しない)全 Promise を await, return, ctx.waitUntil() で処理
REST API で他のバインディングにアクセス直接バインディングを使う (ネットワークホップ・認証不要)
DB に直接 TCP 接続Hyperdrive 経由で接続プール。直接接続は 300-500ms のオーバーヘッド

8. ユースケース / 事例

Vercel Edge Middleware 事例

企業パターン効果
SumUpパーソナライズ + A/B テストフリッカーなしの実験。バリアントを即座に表示
HashiCorpGeo ベースのローカライゼーション外部サービスなしで言語・通貨を自動切替
Super (Notion→Web)マルチテナント URL リライト複数サイトを1つのコードベースで Lighthouse スコア高水準維持
Clerk認証1ms 未満の JWT 検証。フリッカーなしの認証体験

パフォーマンス実測値

指標値ソース
TTFB 削減60-80% (グローバルユーザー)複数ソース
Edge Runtime cold start<1ms (V8 Isolate) vs 数百ms (コンテナ)Cloudflare / Vercel
Vercel Edge TTFB 平均~70msVercel
Edge cold start vs Serverless最大 9x 高速Vercel
Backend コスト削減40-60% (API キャッシュ)複数事例
Edge Function 採用増287% YoY (2025)業界調査

Edge 配置の判断フレームワーク

3つの質問で判断:

  1. ユーザーは地理的に分散しているか? → 分散していなければ Edge の恩恵は限定的
  2. ロジックは Edge Runtime の制約内で実行できるか? → CPU 10-50ms、Node.js API 制限、バンドルサイズ制限
  3. Edge 化で合計レイテンシは実際に下がるか? → ボトルネックが移動するだけではないか (Data Gravity)

推奨導入順序

graph LR
    S1["Step 1<br/>Middleware<br/>認証, リダイレクト<br/>セキュリティヘッダ"] --> S2["Step 2<br/>Feature Flags<br/>A/B テスト<br/>Edge Config / KV"]
    S2 --> S3["Step 3<br/>API キャッシュ<br/>stale-while-revalidate<br/>レスポンスキャッシュ"]
    S3 --> S4["Step 4<br/>Edge SSR / RSC<br/>パーソナライズ<br/>BFF"]

低リスク・高リターンの Middleware から始め、段階的に Edge 化の範囲を広げる。

押さえどころ(カード化候補)

関連

Graph