Upgrade to Pro — share decks privately, control downloads, hide ads and more …

1MBの壁にぶつかった話

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

 1MBの壁にぶつかった話

Avatar for 赤神青空

赤神青空 PRO

September 03, 2026

Video

More Decks by 赤神青空

Other Decks in Programming

Transcript

  1. ▪アンケートの集計ツール/NestJS 前提:本番だけ Data API を挟んでいる + TypeORM + Aurora ローカル開発環境

    Docker の PostgreSQL に通常のドライバで直結 結果セットのサイズ上限がない だから、このバグは一度も再現しない 本番環境 Lambda から Data API 経由で Aurora へ VPC 内に Lambda を置かずに済む構成 1クエリの結果セットは 1MB まで この一点の差だけが、今日の話の全てです。 今ココ 前提 2/10
  2. ▪コードから立てた仮説は、どれも「形は合っている」 外れた仮説 500 が返る経路として、まず2つを疑った。 どちらも、症状の形とは矛盾していなかった。 01 02 判定が failure だと例外

    → そのまま 500。「403 ではなく 500」と 形が合う 前日に修正を2件入れていた。調べたら dev 止まりで本番未反映だ った 認可ライブラリ 今ココ 調査 デプロイ不整合 4/10
  3. ▪本番の ログ1行で確定した Lambda ロググループに、同じ例外が繰り返し出ていた The result exceeds the size limit

    1 MB. Data API の仕様 1クエリの結果セットは 1MB まで。超えると API が 400 を 返す。 設定では変えられない Data API 側の固定値。結果サイズを減らして下回らせるし かない。 フレームワークがこの例外を拾えず、そのまま 500 になって画面に出ていた。 今ココ 真因 5/10
  4. ▪552 行 既定では、1本の LEFT JOIN になる = 46 回答 ×

    12 設問。各行に回答データが丸ごと乗る 意図している姿 実際に返ってきたもの 46 件 552 行(46 回答 × 12 設問) 回答 ︙ 回答A 回答データ 4.8KB 設問1 回答データ 4.8KB 回答B 回答データ 4.8KB 設問2 回答データ 4.8KB 設問3 回答データ 4.8KB 設問4 回答データ 4.8KB 合計 220KB 設問への回答 LEFT JOIN 552 行 値だけの軽い行 ︙ 同じ回答データが 552 回コピーされる 結果セットのサイズ(概算) 上限 1MB ︙ 概算 2.5MB 回答データは 46 個ぶんだけ 1MB を超えた瞬間に Data API が 400 1MB に対して十分に軽い アプリ側は拾えず、そのまま 500 1行に付いている重い荷物が、552回コピーされている(2.5MB は概算) 今ココ 真因 7/10
  5. ▪まだ答えていない設問には、行がそもそも存在しない 伏線回収:このバグは時間とともに発症する 行が増える → 回答が集まる 行が増える → 回答データの複製も 閾値へ 設問が埋まっていく

    昼は開けたのに夜は落ちた その日のうちに回答が集まり、閾値を越 えた。 今ココ 真因 その分だけ増える 壊れ方が特殊 リリースを疑っても、原因はそこにな い。 突然 500 デプロイなしで 壊れる 静かに近づく 動いているうちは、誰も気づけない。 8/10
  6. ▪上限は変えられないので、結果サイズを減らす 直し方 01 直積をやめる(relationLoadStrategy) テーブルごとに別クエリで取らせる。552行 → 46行 + 軽い552行に分かれ、掛け算の構造が消える。 02

    重いカラムを読まない(射影) 一覧が使うのは受付番号と回答者名だけ。必要な列だけ取ると1件 数KB → 百数十バイト。余裕が2桁変わる。 03 それでも上限との距離は残る 設問への回答は 回答件数 × 設問数 で育つ。12設問なら回答800件規模で再び当たる(概算)。 今ココ 対処 9/10