これはCloudflare上でAI関連プロダクトを運用する記録シリーズの1本である。自社プロダクト「カンタン補助金」は、外部の補助金情報を取り込んで内容を補うLLM呼び出し付きのWorkflowを持っている。前回の記事では完走時INSERTだけのWorkflowに実行中の状態が無かった問題を扱った。今回はこのWorkflowを初めて本番で動かした際に出た4つの問題をまとめる。
この記事で分かること
- 単体テスト139件が通っていたのに本番で何が出たか
- それぞれの問題になぜ気づけなかったか
- どのように直し、以後どう検証しているか
この記事で分からないこと(正直に書く)
- 単体テストのカバレッジをどこまで引き上げれば同種の問題を事前に防げたか
- 他のLLM呼び出し付きWorkflowにも同様の問題が潜んでいないかの網羅的な点検結果
何をしたか
外部の補助金情報API から取得した内容をもとに、様式の要否や審査基準をLLMで補完するWorkflowを新設した。単体テストは139件用意し、全て通過していた(出所: 自社の運用記録、確認日2026-09-06)。単体テストが通った状態で、件数を絞った小規模な条件で本番のデータベースと外部APIに対して初めて動かした。
何が起きたか
本番で小さく動かして初めて、4つの問題が見つかった(出所: 自社の運用記録、確認日2026-09-06)。1つ目、候補を絞り込むSQLに関連テーブルとのJOINを足したところ列名が衝突し、「ambiguous column name」エラーで再試行を繰り返した。2つ目、データベース内部のIDに付いていた外部API向けではない前置きを外さずに渡していたため404になり、対象が全件「skipped」として静かに終わっていた(LLM呼び出しが0件だったことが手がかりになった)。3つ目、1ステップに複数件をまとめたところ、1件2〜4分かかる処理が3件分でタイムアウトし再試行した。4つ目、画面の「対応が必要な件数」は上位一定件数までしか返さないクエリの配列の長さをそのまま表示しており、実際の総数とは異なっていた。
なぜ気づけなかったか
単体テストはモックしたデータベースと外部APIに対して書かれており、実際のテーブル構成や実データのID形式、外部APIの応答時間までは再現していなかった(出所: 自社の運用記録、確認日2026-09-06)。139件のテストは、ロジックの単位としての正しさしか保証しておらず、本番データと組み合わせて初めて表面化する問題までは防げなかった。
どう直したか
JOINによる列名衝突は、外側のSELECTを対象テーブル単独のFROMに保ち、欠けているかの判定は相関副問い合わせに置き換えて解消した。ID問題は、外部APIへ渡す直前に前置きを取り除く関数を挟み、データベース側のIDはそのまま保つようにした。タイムアウトは1ステップで扱う件数を1件に減らして解消し、件数表示の誤りは上限を付けない件数取得クエリを別に用意して差し替えた(出所: 自社の運用記録、確認日2026-09-06)。対応は2026年9月に完了している。
再発防止
以後、LLMを呼び出すWorkflowは、単体テストが通った段階では本番投入とみなさず、件数を絞った小規模な条件で本番のデータベースと外部APIに対して1回動かしてから、通常運用の頻度に載せることにしている。件数を小さくして起こすことで、影響範囲を抑えながら実データ特有の問題を早期に洗い出せる。
本番で小さく動かしてから確かめるという考え方は、D1コストの記事の索引最適化や、実行中の状態が無かったWorkflowの記事とも通じている。輪をつなぐと、この記事の次はD1コストの記事に戻る。ストレージ・コストの全体像は姉妹記事「コストとストレージの記事」を参照してほしい。
自社プロダクトのCloudflare Workflows・LLM連携について相談したい場合は、お問い合わせから編集部まで連絡してほしい。
よくある質問
Q1. 単体テスト139件が通っていたのに、なぜ本番で問題が出たのか
単体テストはモックしたデータベースと外部APIに対して書かれており、実際のテーブル構成や実データのID形式、外部APIの応答時間までは再現していなかった。ロジックの単位としての正しさは保証されていたが、実データと組み合わせて初めて出る問題までは防げなかった。
Q2. 見つかった4つの問題とは何か
関連テーブルとのJOINで列名が衝突しエラーになった問題、データベース内部のIDをそのまま外部APIへ渡して404になり全件が静かにskippedになった問題、1ステップに複数件を詰め込みタイムアウトした問題、上位一定件数までの配列の長さを件数として表示していた問題の4つである。
Q3. どうやって直したのか
JOINは相関副問い合わせに置き換え、IDは外部APIへ渡す直前に前置きを取り除き、1ステップで扱う件数を1件に減らし、件数表示は上限を付けない件数取得クエリの結果に差し替えた。
Q4. 以後、同じ問題を防ぐために何を変えたのか
単体テストが通った段階では本番投入とみなさず、件数を絞った小規模な条件で本番のデータベースと外部APIに対して1回動かしてから、通常運用の頻度に載せることにしている。