BigQueryのinsertAllで413エラーが出る本当の理由。load jobへの切り替え判断基準

BigQueryのinsertAllで413エラーが出る本当の理由。load jobへの切り替え判断基準
ある月曜の朝、Slackに通知が飛んできました。
「先週末から、毎朝動いていたBigQueryへの転記ワークフローが4日連続で止まっています」
n8nの実行ログを見ると、エラーは明確でした。
413 Request Entity Too Large
ワークフローの定義は半年前から変更なし。コードもいじっていない。それなのに、ある日を境に突然413が出始めた。原因は、業務データが時間とともに増えて tabledata.insertAll(=1件ずつBigQueryに流し込むREST APIの方式)の10MB上限を超えたことでした。
この記事では、BigQueryへのバッチINSERTで413が出る根本理由と、insertAll から load job にいつ切り替えるべきかの判断基準をまとめます。
エラー対処早見表
まず手元で起きている413をどう捌くか。原本の判断軸を一覧にしました。
状況 | 原因の可能性 | 取るべき対処 |
|---|---|---|
急に413が出始めた / 定義は無変更 | データ増でリクエストが10MB超過 | 後述の判断基準でload jobへ移行 |
数千行までで当面しのぎたい | バッチが大きすぎる | 500行ずつに分割(暫定) |
全件削除→全件挿入で運用中 | データ増がそのままサイズ増 | 差分更新化(MERGE)に変更 |
数十万行を超える規模 | streaming insertは非効率 | GCS経由のload jobへ |
結論:5MBを超える可能性が見えた時点でload jobに切り替える
要点はシンプルです。
tabledata.insertAllのHTTPリクエスト本体は10MB上限。超えると413が返る- データは時間とともに必ず増える。想定2年後に5MBを超えるなら、初期からload jobで設計する
- 「全件削除→全件挿入」設計は罠になりやすい。可能なら差分更新化する
なぜ10MBではなく5MBで切り替えるのか。上限値の意味を含めて説明します。

BigQueryのINSERT方式と上限値(暗記用)
BigQueryには複数のINSERT方式があり、それぞれ上限が違います。
tabledata.insertAll(REST API、いわゆるstreaming insert)
- HTTPリクエスト本体: 最大10MB(超えると
413 Request Entity Too Large) - 1リクエストあたり: 最大10,000行、推奨500行
- 1行あたり: 最大10MB
- 反映: リアルタイム(クエリで即見える)
n8nの「BigQuery」ノードや、https://bigquery.googleapis.com/bigquery/v2/projects/.../tabledata:insertAll への直接POSTがこの方式になる。
bq load(ローカルファイル)
load job=ファイルをまとめてBigQueryに読み込ませる方式です。1件ずつではなく一括で投げる。
- 1ファイル: 最大1GB
- 反映: バッチ(数秒〜数十秒の遅延あり)
bq load(GCS経由)
- 1ファイル: 最大5TB
- スループット最大、コスト最小(streaming insertより安い)
実話:6,708件で10.85MBに達した日

冒頭の事例の続きです。
止まったワークフローは、ある業務SaaSのレコードを毎朝BigQueryに全件転記するものでした。
- 半年前の構築当時: レコード数 約3,000件、リクエストサイズ 約4.5MB。余裕で動いていた
- 4日前の実行時: レコード数 6,708件、リクエストサイズ 10.85MB。413で停止
10MBの壁を超えた瞬間、ワークフローは完全停止。バックフィルもできず、4日分のデータが欠損しました。
「全件転記」設計だったので、レコード数の増加がそのままペイロードサイズに反映されてしまった。これは初期設計の判断ミスです。建てた当時は3,000件で動いていても、業務が拡大すれば6,000、10,000と増える。10MBはあっという間に超えます。
業務データをBigQueryに流す経路そのものの設計は、n8nをCloud Runに段階移行する設計でも触れた通り、投入方式の選択が後々の安定性を左右します。
いつload jobに切り替えるか。判断基準3つ

基準1: 想定2年後のデータ量で5MBを超えるか
現在のリクエストサイズではなく、2年後の想定量で判断します。10MBに直接突き当たる手前で切り替えるため、5MBが安全マージン込みの目安になる。
行数 × 平均行サイズ × 2年後の想定成長率
業務データは年30〜100%増えることが多いので、初期1MBでも2年で5MBは現実的なラインです。
基準2: 「全件削除→全件挿入」設計になっていないか
これが一番ハマるパターン。「シンプルでわかりやすいから」という理由で全件INSERTにすると、データ増加がそのままリクエストサイズに直結します。
差分更新化(last_modified_time でフィルタしてMERGE)に切り替えるだけで、リクエストサイズは劇的に小さくなる。
基準3: ピーク時のバッチサイズが推奨500行を超えるか
insertAll は1リクエスト最大10,000行ですが、推奨は500行です。これを超えるなら、内部的に分割しているか、それとも一発で投げているかを確認します。一発で投げているなら、サイズと併せて切り替え検討対象になる。
n8nで実装する場合の選択肢
選択肢A: insertAllのまま、Code + Split In Batchesで分割
最小変更で済む暫定対処です。
// Code ノード
const rows = items[0].json.rows
const batchSize = 500 // 5MB/バッチ目安に調整
const batches = []
for (let i = 0; i < rows.length; i += batchSize) {
batches.push({ json: { rows: rows.slice(i, i + batchSize) } })
}
return batches
これを Split In Batches → BigQuery insertAll に流します。実装30分、ただし根本解決ではない(さらに増えれば1バッチが5MBを超える)。
選択肢B: BigQuery node の Load Table モードに切り替え
n8nのBigQueryノードには Load Table モードがあり、これを使うとload job APIで投げてくれる。
- メリット: 上限が事実上気にならなくなる
- デメリット: スキーマ定義が必要、リアルタイム反映ではない(数秒の遅延あり)
選択肢C: GCS経由のload job(大規模向け)
GB級になったら、いったんGCSにNDJSONを書き出してから bq load gs://... で取り込みます。
- メリット: コスト最小、スループット最大
- デメリット: GCSバケット管理が増える
選び方の目安: 数千行までは選択肢B、数十万行を超えるなら選択肢C。
アンチパターン3つ
アンチパターン1: 「とりあえずinsertAllで動いているからOK」
初期は動きます。問題は時間が経ってから出る。データ量の伸びを設計時に見越さないと、ある朝突然413で止まります。
アンチパターン2: 413が出てから「上限あったの?」と慌てる
tabledata.insertAll の10MB制限は、Google Cloudの公式ドキュメントの「クォータと上限」セクションに明記されています。実装前に読むのが本来です。
アンチパターン3: 全件削除→全件挿入で「現状はこれで足りる」設計
「業務データは時間とともに必ず増える」というのが鉄則。最初は3,000件でも、3年後には30,000件になります。差分更新化の手間を惜しむと、必ずあとで返ってくる。
まとめ:データ量の伸び代を設計時に必ず見積もる
BigQueryへのバッチINSERTで413を避けるには、次の3点を設計時に押さえておく。
- 想定2年後の量で5MBを超えるなら、初期からload jobを選ぶ
- 「全件削除→全件挿入」設計はやめて、差分更新化する
tabledata.insertAllの上限値(10MB / 10,000行)を覚えておく
insertAll は実装が簡単で、n8nやGASからも書きやすいので、つい採用しがちです。それでも業務データは時間とともに必ず増えるので、初期の段階で「全件INSERTのまま伸ばすか、差分更新化するか」を判断しておくのが、長期的に壊れない設計の条件になる。
データ基盤の設計でお困りなら
毎朝動いていたBigQueryへの転記が急に止まった、データが増えるたびに手当てに追われている、そもそも何件まで耐えられる設計なのか誰も把握していない。こうした「動いてはいるが壊れる前提が見えていない」状態は、データが増えるほど対処が重くなります。
f2t.jpでは、データ基盤の設計から、スケーラビリティ問題の事前回避まで一貫してお手伝いしています。お問い合わせフォームからお気軽にどうぞ。
この記事のテーマに合うサービス:業務フロー自動化
スプレッドシート・メール・Slackの往復を、自動化で終わらせる



