テック技報最新号へ →
コード

nginx: SSE(ストリーミング応答)は proxy_buffering を切る

nginx はアップストリームの応答を既定でバッファしてから返すので、Server-Sent Events や逐次出力のレスポンスが「まとめてドサッと」届く。手元では滑らかなのに本番だけ遅く見えるときは、まずここを疑う。

@amitsinha__07 · 投稿 2026-10-19
#nginx#sse#streaming#infra

どんな時に気にする?

  • SSE・チャンク転送でトークンや進捗を逐次返す API(LLM のストリーミング、ログのライブ表示など)
  • ローカルでは 1 つずつ流れるのに、nginx を挟んだ本番では数秒おきに固まって届く
  • 最初の 1 バイトが届くまでの時間(TTFB)だけが本番で悪い

対処(どちらか)

  1. nginx 側でストリーミングするパスだけバッファを切る
    nginx
    location /api/stream {
        proxy_pass http://app;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_buffering off;        # 応答を溜めずにすぐ流す
        proxy_cache off;
        proxy_read_timeout 1h;      # 長時間つなぎっぱなしの接続が 60 秒(既定)で切られないように
    }
  2. アプリ側から、そのレスポンスだけバッファしないよう指示する
    ts
    // Hono / Express など、どのフレームワークでもヘッダーを足すだけ
    c.header("Content-Type", "text/event-stream");
    c.header("Cache-Control", "no-cache");
    c.header("X-Accel-Buffering", "no"); // nginx がこのレスポンスだけバッファしない

    nginx の設定を触れない環境(共用のリバースプロキシなど)ではこちらが楽。

注意点

  • gzip on が効いていると、圧縮のために溜められて同じ症状になることがある。text/event-stream は gzip_types に入れない。
  • nginx の手前に CDN やロードバランサがある場合、そちら側のバッファリングも確認する(nginx だけ直しても治らないことがある)。
  • proxy_buffering off を server 全体に付けると、普通の API でも遅いクライアントに nginx のワーカーが引きずられる。ストリーミングのパスに限定する。

出典

X の元の投稿を開く