Skip to content

✍️ 필사 모드: 2026 年の realtime web — WebSocket・SSE・WebTransport・WebRTC 深掘り比較(LLM streaming が SSE を選んだ理由まで)

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

プロローグ — 「realtime」という言葉の罠

「realtime 機能を入れてほしい」という依頼が来る。最初に頭に浮かぶ言葉は WebSocket だ。とりあえず WS server を立て、router の後ろに sticky session を付け、token 認証を乗せる。半年後、同じ会社の別チームが LLM の token を stream していて — 不思議なことに — SSE を使っている。誰かが訊く: 「なんで WebSocket じゃないの?」

答えは単純ではない。「realtime」は単一の問題ではなく spectrum である。

  • chat の 1 行を世界の 1 万人に 50 ms 以内 — 双方向・低遅延。
  • LLM の token を 1 人のユーザーに 1 分間 — 一方向 stream。
  • game の座標を毎秒 60 回、packet が 1 つ落ちても次が追いつくならよし — 多対多・unreliable datagram。
  • 通話の video / audio に補助 data — P2P media。
  • 5 分に 1 度 push を端末に — それは push であって realtime ではない。

それぞれに合う protocol が違う。この記事は 2026 年時点の 5 候補 — WebSocket、Server-Sent Events (SSE)、WebTransport、WebRTC DataChannel、long polling — を比較する。おまけに HTTP/2 Server Push がなぜ死んだか、LLM streaming のほぼ全部が SSE に収束した本当の理由まで。

TL;DR. 一方向 streaming なら SSE。双方向・低遅延なら WebSocket。game 系の unreliable multi-stream なら WebTransport。P2P や media なら WebRTC。そして — 正直に言うと — ただの polling で足りる場合も多い。


1 章 · 風景 — 2026 年の 5 つの protocol

        Browser ◀──────── Server (または別の browser)
        ───────────────────────────────────────────────
        WebSocket           双方向、TCP、frame 形式
        SSE (EventSource)   server から client への一方向、HTTP 上
        WebTransport        双方向、QUIC/HTTP3、多重化
        WebRTC DataChannel  P2P、UDP/SCTP、unreliable も可
        Long Polling        HTTP polling、response を保留

各 protocol を 1 行で:

  • WebSocket — 1 本の TCP 上に双方向 frame。2011 年標準化、最も普及、最もよく知られた落とし穴も多い。
  • Server-Sent Events — HTTP response を閉じずに text を流す。text/event-stream MIME、自動 reconnect 内蔵。一方向 (server → client)。
  • WebTransport — QUIC 上の双方向。信頼 stream + unreliable datagram を 1 本の接続で。head-of-line blocking なし。Chrome stable で利用可能。
  • WebRTC DataChannel — 2 つの peer 間の直接接続。P2P、任意で unreliable。運用は最難。
  • Long Polling — 古い友人。response を保留してイベント発生時に応答。あらゆる環境で動く。

そして死者: HTTP/2 Server Push. Chrome が 2022 年に無効化し、仕様からの削除が進行中。cache 動作が微妙で、実利益が小さかった。


2 章 · WebSocket — まだ働き者、まだ落とし穴

WebSocket は 2011 年に RFC 6455 として標準化された。要点は単純だ: HTTP/1.1 の Upgrade ヘッダで接続を開始し、以後は TCP 上で独自 frame (text / binary / Ping / Close) を双方向に流す。

頭の中の模型

        Client                          Server
          │  GET /ws HTTP/1.1               │
          │  Upgrade: websocket             │
          │ ──────────────────────────────▶ │
          │                                 │
          │ ◀────────────────────────────── │
          │  HTTP/1.1 101 Switching         │
          │                                 │
          │   ◀══════ frame ══════▶         │  (双方向)
          │   ◀══════ frame ══════▶         │
          │                                 │
          │   Close 0x88                    │

Upgrade handshake が終わるとその TCP 接続はもはや HTTP ではない。だから router・load balancer・proxy・CDN の挙動が微妙になる。

強み

  • 真の 双方向。client もいつでも送れるし、server もいつでも送れる。
  • 低遅延。handshake は 1 回、以降の frame overhead は 2〜14 byte。
  • binary 安全。game や binary protocol に直接使える。
  • ほぼ全ての browser・言語・SDK が対応。

落とし穴

  1. HTTP/2 ではない。 WS 自体は HTTP/1.1 の upgrade。RFC 8441 で HTTP/2 上 WebSocket が可能だが server 実装が一様でない。
  2. sticky session が必須。 WS 接続は同じ backend インスタンスに固定される必要があり、Pub/Sub のような fan-out 層が要る。
  3. head-of-line blocking。 1 本の TCP なので、1 つの大きな message が後続を塞ぐ。
  4. 自動 reconnect なし。 自分で書く — exponential backoff、再送 queue、sequence number。
  5. proxy 非互換。 一部の企業 proxy は WS handshake を切る。
  6. HTTP cache を回避。 GET ではないので CDN cache の恩恵なし。

小さな chat server (Node-ish + ws)

// server.ts — minimal WS echo + broadcast
import { WebSocketServer } from 'ws'

const wss = new WebSocketServer({ port: 8080 })
const clients = new Set<WebSocket>()

wss.on('connection', (ws) => {
  clients.add(ws)
  ws.send(JSON.stringify({ type: 'welcome', count: clients.size }))

  ws.on('message', (raw) => {
    const msg = JSON.parse(raw.toString())
    for (const c of clients) {
      if (c !== ws && c.readyState === 1) {
        c.send(JSON.stringify({ ...msg, ts: Date.now() }))
      }
    }
  })

  ws.on('close', () => clients.delete(ws))
})

client 側:

const ws = new WebSocket('wss://example.com/ws')
ws.onopen = () => ws.send(JSON.stringify({ type: 'hello', name: 'Jun' }))
ws.onmessage = (e) => console.log('recv:', JSON.parse(e.data))
ws.onclose = () => {
  // reconnect ロジックは自分で書く — backoff、jitter、token refresh、...
}

これで終わりではない。production では — 認証・heartbeat・reconnect・message queue・rollout 時の graceful drain — まで含めて数百行に育つ。


3 章 · Server-Sent Events — LLM streaming が選んだ伏兵

SSE は 2009 年に HTML5 仕様に入った。あまりに単純で長らく軽く見られていたが、2024〜2026 年の LLM streaming brew によって 事実上の標準 になった。

頭の中の模型

        Client                                Server
          │ GET /stream HTTP/1.1                 │
          │ Accept: text/event-stream            │
          │ ──────────────────────────────────▶  │
          │                                      │
          │ ◀──────────────────────────────────  │
          │ HTTP/1.1 200 OK                      │
          │ Content-Type: text/event-stream      │
          │                                      │
          │ ◀── data: {"token":"hello"}\n\n     │
          │ ◀── data: {"token":" world"}\n\n    │
          │ ◀── data: [DONE]\n\n                 │
          │                                      │
          │   (response が閉じない)              │

接続はただの HTTP response。server は response を閉じずに data: ...\n\n 形式で 1 行ずつ流す。client は EventSource で自動 parse・自動 reconnect。

強み

  • 単純。 HTTP のまま。header・method・cache 規則そのまま。
  • 自動 reconnect。 EventSource が切れたら自動で再接続、Last-Event-ID で resume。
  • firewall friendly。 普通の HTTP、どんな proxy も通過。
  • HTTP/2・HTTP/3 を自動で活用。 多重化もタダ。
  • 一方向 = server logic が単純。 Pub/Sub fan-out に自然に合う。
  • CDN・gzip 互換。 response であって upgrade ではないため。

弱み

  • 一方向のみ。 client → server は別の POST が要る (それが LLM API の形)。
  • text 専用。 UTF-8 text のみ — binary は base64 で非効率。
  • 接続数の上限。 HTTP/1.1 では origin あたり 6 — HTTP/2 ではほぼ無制限。
  • timeout。 一部の proxy (特に nginx の default) は idle response を切る — 定期的な keep-alive コメントが要る。

なぜ LLM streaming が SSE を選んだか

OpenAI、Anthropic、Google Gemini、Cohere — ほぼ全ての LLM token streaming API が SSE。出典: OpenAI Streaming docs https://platform.openai.com/docs/api-reference/streaming、Anthropic Messages Streaming https://docs.anthropic.com/en/api/messages-streaming。理由は 7 つ:

  1. 本質的に一方向。 prompt は 1 回の POST、答えは token ごとに流れる。WS の双方向は不要。
  2. retry が自然。 通常の HTTP retry 方針 (429・5xx) がそのまま動く。
  3. 認証・rate limit・課金が標準 HTTP middleware に乗る。 WS は毎回自前。
  4. firewall・proxy 通過。 企業網で WS は塞がれることがある。
  5. CDN と相性。 Cloudflare・Vercel Edge Functions が SSE を一級でサポート。
  6. test が簡単。 curl -N で終わり。
  7. HTTP/2・HTTP/3 で多重化が無料。 同時 stream が 1 本の接続を共有。

WebSocket を使うとこの 7 つが全て自前項目になる。

30 行 token streamer (Bun / Node)

// app/api/chat/route.ts — 30 行 SSE token streamer
export const runtime = 'edge'

export async function POST(req: Request) {
  const { prompt } = await req.json()

  const stream = new ReadableStream({
    async start(controller) {
      const encoder = new TextEncoder()
      const send = (data: unknown) => {
        controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`))
      }

      // 仮想 LLM: 50 ms ごとに token を送る
      const tokens = ['こん', 'にちは', '、', ' SSE', ' demo', ' です', '。']
      for (const t of tokens) {
        send({ token: t })
        await new Promise((r) => setTimeout(r, 50))
      }
      send('[DONE]')
      controller.close()
    },
  })

  return new Response(stream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache, no-transform',
      Connection: 'keep-alive',
    },
  })
}

client 側 — EventSource は POST を受けないので、fetch streaming または SSE parser (例: eventsource-parser) を使う。

const res = await fetch('/api/chat', {
  method: 'POST',
  body: JSON.stringify({ prompt: 'hi' }),
  headers: { 'Content-Type': 'application/json' },
})
const reader = res.body!.getReader()
const decoder = new TextDecoder()
let buf = ''
while (true) {
  const { done, value } = await reader.read()
  if (done) break
  buf += decoder.decode(value, { stream: true })
  for (const line of buf.split('\n\n')) {
    if (line.startsWith('data: ')) console.log(line.slice(6))
  }
  buf = ''
}

これが ChatGPT・Claude UI の token streaming の正体だ。40 行で終わる。


4 章 · WebTransport — HTTP/3 時代の新しい働き者

WebTransport は IETF が 2024 年に RFC 9484 として標準化した新 protocol。QUIC 上の双方向 + datagram を 1 本の接続で提供する。出典: https://developer.mozilla.org/en-US/docs/Web/API/WebTransport_API

頭の中の模型

        Browser ──────── QUIC (UDP 上) ──────── Server
                ├── 双方向の信頼 stream #1
                ├── 双方向の信頼 stream #2
                ├── 単方向の信頼 stream #3
                └── unreliable datagram (UDP のように)

1 本の QUIC 接続上に複数 stream。ある stream の packet loss が他を塞がない — head-of-line blocking がない。WebSocket の最大の弱点が消える。

2026 年 browser サポート

  • Chrome / Edge — stable 対応 (Chrome 97+、2022 年から)。https://chromestatus.com/feature/4854541929873408
  • Firefox — stable 対応 (Firefox 114+、2023 年から)。default 有効化は作業中。
  • Safari — 2026 年 5 月時点で部分対応 (Safari Technology Preview で実験的)。stable の全面有効化はまだ。

server 実装: aioquic (Python)、quinn (Rust)、msquic (Microsoft)、Cloudflare Workers WebTransport API。出典: https://github.com/aiortc/aioquic

強み

  • head-of-line blocking なし。 game や multi-stream content に決定的。
  • 信頼・unreliable の両方。 unreliable datagram は game 座標・VOIP 補助 track に最適。
  • 接続 migration。 QUIC 特性 — Wi-Fi → cellular で IP が変わっても接続が続く。
  • TLS 1.3 必須。 security が default。

弱み

  • Safari 未完。 全ユーザー対象なら fallback が必要。
  • 運用 tool 未成熟。 debugger・logging・metrics の生態系が WS ほど豊富でない。
  • UDP 遮断。 企業網・キャリア網の一部で UDP が塞がれて fallback が必要。
  • 証明書要件。 ドメイン証明書が要る (自己署名なら serverCertificateHashes で pin)。

datagram demo

// game 座標を 30 fps で unreliable datagram として送る
const transport = new WebTransport('https://game.example.com/wt')
await transport.ready

const writer = transport.datagrams.writable.getWriter()
const reader = transport.datagrams.readable.getReader()

setInterval(async () => {
  const buf = new ArrayBuffer(8)
  const view = new DataView(buf)
  view.setFloat32(0, player.x)
  view.setFloat32(4, player.y)
  await writer.write(new Uint8Array(buf))
}, 33)

;(async () => {
  while (true) {
    const { value, done } = await reader.read()
    if (done) break
    const view = new DataView(value.buffer)
    other.x = view.getFloat32(0)
    other.y = view.getFloat32(4)
  }
})()

これを WebSocket で同じことをしようとすると、座標 1 packet が遅れたら後続が塞がる。WebTransport はただの新しい datagram。落ちたら落ちたまま、次へ。


5 章 · WebRTC DataChannel — P2P の王、運用の地獄

WebRTC は本来 video call 用に作られた。RTCDataChannel は同じ P2P 接続上に任意の data を流せる兄弟 API。

頭の中の模型

        Peer A                         Peer B
          │     (signaling server)       │
          │ ───── SDP offer ────────▶   │
          │ ◀──── SDP answer ─────────  │
          │ ───── ICE candidates ───▶   │
          │ ◀──── ICE candidates ─────  │
          │                              │
          │  ╔════ P2P SCTP/UDP ════╗   │
          │  ║   DataChannel        ║   │
          │  ║   Video/Audio        ║   │
          │  ╚══════════════════════╝   │

要点は signaling が別 であること。WebRTC は 2 peer の IP・port・media 能力を交渉する間、message を運ぶ channel が要る — それが signaling server (通常 WebSocket か SSE)。

強み

  • 真の P2P。 server を経由しないので遅延が最低、server 帯域も不要。
  • unreliable mode。 ordered: false, maxRetransmits: 0 で UDP 的に。
  • NAT 越え。 STUN・TURN 基盤で NAT 越しの user も繋ぐ。
  • media と一体。 video call に data channel を 1 本の接続で乗せられる。

弱み

  • 運用が最難。 signaling server + STUN server + TURN server (NAT 越え失敗時の fallback) — 3 つの基盤。
  • TURN は P2P ではない。 TURN に fallback すると実質 server relay で、帯域・課金が暴走。
  • 接続時間が長い。 数百 ms〜数秒の ICE 交渉。
  • browser 互換性の細部差異。 Chrome / Firefox / Safari が端で違う動き。

使いどころ

  • video / voice 通話に付随する data (chat・file 転送・game 入力)。
  • 真の P2P game (server cost 削減、遅延最小化)。
  • file 共有 (WebTorrent 系)。
  • metaverse / VR — 位置・表情など高頻度 data。

LLM token streaming に WebRTC を使う人はいない。その刃は用途が狭く、運用負担が重い。


6 章 · long polling — 古い友、死なず

browser は HTTP/1.1 の時代から polling をしてきた。その進化が long polling だ。client が GET を送ると、server は応答を 即座に返さず イベント発生まで保留する。イベントが起きたら応答し、client は即座に再度 GET。

頭の中の模型

        Client                        Server
          │ GET /events                  │
          │ ──────────────────────────▶  │
          │                              │ (event 待機、保留)
          │                              │
          │                              │ event 発生
          │ ◀────── 200 OK [event] ───── │
          │ GET /events?since=...        │
          │ ──────────────────────────▶  │
          │                              │ (また待機)

単純で、動かない環境がない。

強み

  • どこでも動く。 HTTP/1.0 でも。あらゆる proxy が通す。
  • 認証・CORS・cache・CDN がすべて標準 HTTP。
  • state が少ない。 1 request 1 response なので server を stateless に保てる。
  • fallback として最強。 WS・SSE・WT が全部失敗しても polling は動く。

弱み

  • request overhead。 イベントごとに HTTP header の代金。
  • 遅延が揺れる。 response 後、次の GET までに gap がある。
  • timeout の調整。 長すぎれば proxy が切り、短すぎれば普通の polling になる。

2026 年の現実

まだ生きている。特に — mobile SDK の fallback、社内 LAN chat、通知 system — で。SSE が使えない環境 (一部の embedded browser など) でも。「cool でない」と切り捨ててはいけない。


7 章 · 死者 — HTTP/2 Server Push の短い生涯

HTTP/2 Server Push は 2015 年に登場した。きれいな idea だった — client が要求する前に server がリソースを push、page が速くなる。

現実は失望だった。Chrome の telemetry (2020〜2021) では大多数の push が — 既に cache にあるので — 無駄だった。cache 挙動が微妙で、実装が一様でなかった。Chrome は 2022 年に無効化。出典: https://developer.chrome.com/blog/removing-push。仕様からも削除中。

代替。 真のリソース push なら 103 Early Hints + link rel=preload。message push なら SSE。


8 章 · 意思決定 matrix

use case第 1 候補代替備考
LLM token streamingSSEWSserver → client 一方向、retry / CDN friendly
chat (1:1、1:多)WebSocketSSE + POST双方向・低遅延
実時間 multiplayer gameWebTransportWebRTCunreliable datagram、no HoL blocking
dashboard / 実時間 metricsSSEWS一方向、自動 reconnect
協調 editor (CRDT)WebSocketWT双方向 + 順序
通話WebRTCmedia と data を 1 channel
P2P file 転送WebRTCWS relayserver 帯域節約
通知 (低頻度)long pollingSSEserver cost と複雑度を最小化
株 / coin ticker (broadcast)SSEWS一方向、fan-out が単純
IoT 命令 (双方向)WebSocketWT小さな payload、双方向
最終 fallbacklong pollingあらゆる環境を通る

この表は正解ではなく 出発点。決定にはトレードオフがあり、team の運用能力・既存 infra・user の環境が表を揺らす。


9 章 · 正直な意思決定 framework

5 つの質問を順に。

Q1. 真に双方向か、実は一方向か?

LLM の answer は 一方向。prompt は 1 回の POST、answer は token stream。chat message も実は — 送信は POST で完結、受信だけが stream — と見ると一方向。

真の双方向 は 2 方向で同時に message が流れる場合 — 協調 editor の CRDT 更新、multiplayer game の入力 / 状態、IoT の双方向命令。

一方向なら SSE をまず検討。cost・運用・複雑度が圧倒的に低い。

Q2. 信頼が必要か、unreliable でよいか?

chat message・決済 event・状態更新 — 信頼必須。TCP・QUIC stream。

game 座標・VOIP・実時間 sensor — unreliable OK。1 packet 落ちても次が追いつけば終わり。UDP・QUIC datagram。

unreliable が要るなら WebTransport (または WebRTC)。WS には unreliable mode がない。

Q3. P2P が本当に要るか?

P2P は — 本当に — server を経由しない場合だけ。通話、file 転送、真の P2P game。それ以外は client-server が圧倒的に単純。

P2P を決めたら STUN + TURN の基盤 cost・運用を受け入れる覚悟。TURN に fallback したらそれは実質 relay で、P2P の利点は消える。

Q4. 既存 infra は?

会社が既に Kafka + Pub/Sub + nginx で SSE を回しているなら — 新機能に WS を入れない。運用 team が両方を知らないといけなくなる。

WS を既にうまく運用していて、新機能に SSE を導入するなら理にかなう — 2 つの protocol が違う問題を解く場合に限る。

Q5. user の network 環境は?

企業網・キャリア網には — UDP 遮断、WS 遮断、idle response 遮断 — 何でもある。user の環境が多様なら fallback は必須。

        WT 試行 ──失敗──▶ WS 試行 ──失敗──▶ SSE 試行 ──失敗──▶ long polling

production の realtime stack はだいたいこの fallback chain を何らかの形で持つ。


10 章 · 実例 — 誰が何を使うか

  • ChatGPT、Claude、Gemini API の token streaming — SSE。出典: OpenAI https://platform.openai.com/docs/api-reference/streaming、Anthropic https://docs.anthropic.com/en/api/messages-streaming
  • Slack message — 歴史的に WebSocket。2025 年頃 mobile は HTTP polling + push 通知に移行 (battery のため)。
  • Discord — WebSocket (message) + WebRTC (voice / video)。出典: https://discord.com/developers/docs/topics/gateway
  • Figma の同時 editing — WebSocket + 自前 CRDT。
  • Google Docs — long polling から始まり、WebSocket へ移行。
  • Cloudflare Stream / Workers — WebTransport 対応、game / live video 系の load を受ける。
  • Zoom — WebRTC (media) + 自前 signaling。
  • GitHub Live Updates — SSE。
  • Twitch IRC (chat) — TCP + 自前 protocol、web client は IRC を WebSocket の上に乗せる。
  • 株式取引 platform — ほぼ WebSocket (broadcast + 注文) または 自前 binary TCP (desktop)。

パターンが見える — 一方向 streaming は SSE、双方向 chat は WS、media は WebRTC、game は段階的に WT


11 章 · 運用 note — 実際に痛い所

sticky session

WS・WT は client が同じ backend インスタンスに固定される。ALB・Envoy・HAProxy の sticky session 設定が要る。SSE は — response が最後まで 1 インスタンスで流れるが — reconnect ごとに別 インスタンスでも OK (server が stateless なら)。

graceful shutdown

deploy で WS 接続を切ると 1 万人の user が同時に再接続を試みて thundering herd。決まったパターン:

  1. 新規接続を拒否 (health check fail)。
  2. 既存接続に「すぐ切る」message を送る。
  3. client が jitter を入れて自発的に reconnect。
  4. 30〜60 秒後に強制 close。

SSE も同じ問題。long polling は — 1 request が短いので — 運がよい。

認証

WS の Upgrade handshake は HTTP なので cookie・header・token を送れる。ただし — 一部の library は handshake 後に認証を確認 — このパターンは危険。handshake で認証する。

WT は証明書ベース + header。SSE は — ただの HTTP なので — 最も単純。

WebRTC は signaling server で認証。P2P 接続自体は DTLS-SRTP で暗号化。

cost

  • WS・SSE — server compute は接続数に比例。帯域は message 量に比例。
  • WT — 同様だが QUIC の CPU overhead が若干高い (2026 年時点)。
  • WebRTC — server cost は signaling・STUN・TURN。TURN 使用が料金 bomb。
  • long polling — 保留 request あたり CPU・memory + イベントごとの HTTP header overhead。

大規模 (接続 10 万以上) では — 接続あたり memory — が決定的。Node WS は約 30〜50 KB / 接続、Go・Rust は 5〜15 KB。言語選択が運用 cost を左右する。

monitoring

  • WS — 接続数、message throughput、平均接続寿命、reconnect 頻度。
  • SSE — active response 数、response 寿命、encoding error。
  • WT — active session、stream あたり throughput、datagram loss 率。
  • WebRTC — ICE 成功率、TURN fallback 率、media RTT。
  • long polling — RPS、保留時間 distribution。

OpenTelemetry のサポートは — WS 部分、SSE 完全、WT は 2026 年時点で進行中 — と異なる。


12 章 · 自作する WT datagram server (Node、aiortc なし)

browser 側 demo は上にあり、server は Rust の wtransport か Python の aioquic が最も一般的。Node では 2026 年 5 月現在、@fails-components/webtransport が最も成熟。

// server.ts — minimal WebTransport datagram echo
import { Http3Server } from '@fails-components/webtransport'
import { readFileSync } from 'node:fs'

const server = new Http3Server({
  port: 4433,
  host: '0.0.0.0',
  secret: 'demo',
  cert: readFileSync('./cert.pem'),
  privKey: readFileSync('./key.pem'),
})
server.startServer()

const stream = await server.sessionStream('/wt')
const reader = stream.getReader()
while (true) {
  const { value: session, done } = await reader.read()
  if (done) break

  await session.ready
  const dgReader = session.datagrams.readable.getReader()
  const dgWriter = session.datagrams.writable.getWriter()

  ;(async () => {
    while (true) {
      const { value, done } = await dgReader.read()
      if (done) break
      // echo
      await dgWriter.write(value)
    }
  })()
}

demo 用の証明書が要り (browser に自己署名を受けさせるには serverCertificateHashes の pin)、local test 用に Chrome flag を有効化。


13 章 · anti-pattern 10 個

  1. すべての realtime 要件に反射的に WebSocket。 一方向なら SSE が単純・安価。
  2. 認証を handshake 後に。 WS upgrade で認証しないと一瞬未認証の接続を受ける。
  3. 自動 reconnect を書かない。 mobile network で切断は日常。
  4. heartbeat なし。 idle proxy が 30 秒後に切るのに気づかない。
  5. message sequence ID なし。 reconnect 後の重複・欠落を検出できない。
  6. graceful shutdown なしで再 deploy。 自爆 DDoS の thundering herd。
  7. 巨大な単一 message。 WS の head-of-line blocking を自分で起こす。
  8. WebRTC を P2P でない用途に。 client-server なら WS・WT が単純。
  9. HTTP/2 Server Push を復活させようとする。 死者だ。
  10. fallback chain なし。 user の 30 % が企業 proxy の後ろにいるかもしれない。

14 章 · 2026 年予測と未来

  • WebTransport — Safari が stable で default 有効化する瞬間 (2026〜2027 予想) に game / media 系の default 候補になる。
  • HTTP/3 + SSE — 多重化と 0-RTT 再接続が結合し、SSE がさらに強くなる。
  • MoQ (Media over QUIC) — IETF MoQ working group が live media 転送の標準を作っている。出典: https://datatracker.ietf.org/wg/moq/about/
  • edge runtime での SSE 一級サポート — Vercel・Cloudflare・Deno Deploy が SSE を優先。
  • WebSocket over HTTP/3 — RFC 9220、実 adoption はまだゆるやかだが進行中。
  • AI agent workflow — token streaming は SSE、tool 呼び出し結果は SSE event type で分離する pattern が広がる。

LLM 時代以降の realtime web は — 1 つの protocol が全部を解くのではなく — use case ごとに最適 tool を選ぶ時代 だ。WS が全てを解いていた 2010 年代は終わった。


エピローグ — protocol は道具だ

この記事の 1 行要約: 「realtime」という言葉を見たらまず双方向か一方向かを問い、次に信頼 / unreliable を問い、次に P2P かを問う。3 つの問いと 4〜5 行で答えが出る。

LLM token streaming が SSE を選んだのは SSE が「最強」だからではない。その問題に対して SSE が最も単純な答え だからだ。同じ論理で、協調 editor は WebSocket が最も単純、game 座標は WebTransport が最も自然。

道具を愛するな、問題を愛せ。

14 項目 checklist

  1. 双方向は本当に必要か、実は一方向か?
  2. 信頼必須か、unreliable で良いか?
  3. P2P は本当に要るか?
  4. user の network 環境 (企業網・mobile・海外) を想定したか?
  5. fallback chain があるか?
  6. 認証を handshake で行うか?
  7. 自動 reconnect + backoff + jitter があるか?
  8. heartbeat / idle ping があるか?
  9. message sequence ID と resume 仕組みがあるか?
  10. graceful shutdown 手順があるか?
  11. sticky session / session affinity が router に設定されているか?
  12. 接続あたり memory cost を測ったか?
  13. monitoring / SLO が定義されているか?
  14. (LLM なら) SSE をまず検討したか?

anti-pattern 10 個 (要約)

  1. 一方向に WebSocket。
  2. 認証が遅い。
  3. reconnect なし。
  4. heartbeat なし。
  5. sequence ID なし。
  6. graceful shutdown なし。
  7. 巨大単一 message。
  8. WebRTC を P2P でない用途に。
  9. HTTP/2 Server Push 復活の試み。
  10. fallback chain なし。

次の記事予告

候補: edge runtime 上の SSE — Vercel / Cloudflare / Deno での LLM token streaming pattern 比較MoQ (Media over QUIC) 入門 — 次世代 live mediaCRDT + WebSocket — 協調 editor の運用 note

"realtime web の次の 10 年は 1 つの protocol ではなく — 問題に合う道具を選ぶ — 時代だ。一方向なら SSE、双方向なら WebSocket、unreliable multi-stream なら WebTransport、P2P なら WebRTC。そしてそれでも足りなければ long polling はまだ生きている。"

— 2026 realtime web 深掘り、終わり。


参考 / References

현재 단락 (1/393)

「realtime 機能を入れてほしい」という依頼が来る。最初に頭に浮かぶ言葉は WebSocket だ。とりあえず WS server を立て、router の後ろに sticky session ...

작성 글자: 0원문 글자: 19,448작성 단락: 0/393