AIと本番のプロダクトを作ると、コードは速く書けます。一方で、運営会社が経験した事故は、エラーが出ない形で起きました。
9件を並べると、共通していたのはコードの誤りそのものより、それが見つからないまま通ってしまう確認の仕方でした。「何を確かめれば安全か」を決める仕事が、人に残っていました。
どんな環境で起きた話か
運営会社は2026年、採用領域のSaaS、営業メッセージの自動送信ツール、日程調整ツール、データベースを持つWebメディアなどを、Claude Codeなどのコーディングエージェントと一緒に作り、本番で運用しています。
黙って欠けた:件数の事故
件数の事故は、エラーも警告も出ませんでした。画面や実行結果だけでは、欠けたことに気づけません。
事故1:1,000件で切れたデータで、二重送信した
起きたこと:営業メッセージの自動送信ツールで、送付済みの宛先をDBから書き出し、次の送付リストの除外に使いました。宛先は1万件を超えていたのに、取得できたのは1,000件だけでした。
除外から漏れた100社以上に、同じ差出人から2通目を送りました。
AIだけでは防げなかった理由:Supabaseの公式ドキュメントには、既定では最大1,000行までしか返さない(設定で変更できる)と書かれています。このときは上限に当たってもエラーや警告が出ず、コードは正常に動き、出力も整っていました。
「全件のはず」を疑う材料が、どこにもありませんでした。
人がしたこと:全件が必要な取得はページングで回し、返った件数が1,000未満になるまで続けます。PostgRESTは
Prefer: count=exactを付けると、応答のContent-Rangeヘッダに総数を返します。取得後に総数と取得件数を突き合わせ、一致しなければ止める検査を入れました。除外リストのように、取りこぼしが実害になる用途では必須にしています。
事故2:「処理しました」の報告が、約4分の1だった
起きたこと:寺社の公式サイト約460件の情報を、軽量なLLMのエージェントに抽出させました。あるバッチは「39件処理した」と報告しましたが、実際の出力は9件でした。
別のバッチでは、「授与あり」と判定された全件に根拠がありませんでした。
AIだけでは防げなかった理由:入力が大きいと、エージェントは時間や入力の上限に達し、残りを省略したり推測で埋めたりします。完了の報告は自己申告なので、報告文を読むだけでは完了に見えます。
Anthropicの公式ガイドも、対策で幻覚は大きく減るが無くならない、重要な情報は検証するよう書いています。
人がしたこと:入力を、キーワード前後だけを抜いた1ファイルに軽量化しました。自己申告ではなく、出力ファイルの数をスクリプトで数えて未処理を再実行しました。
抽出結果には原文の抜粋(根拠)を必須にし、原文と一致するかを機械で照合して、一致しない根拠は捨てました。埋めきれない分は決まったルールで保守的に埋め、不明は空にしました。
手元では通った:権限と認証の事故
権限の事故は、手元の確認がすべて成功したことが原因でした。確認した場所が、本番と違う権限で動いていました。
事故3:「行単位の制御が有効だからOK」という判定
起きたこと:自社SaaSのセキュリティ監査で、AIは最初「RLS(行単位のアクセス制御)が有効なので問題なし」と判定しました。人が調べ直すと、プロフィールの更新ポリシーに、更新後の値を縛る条件がなく、ユーザーが自分の行の組織IDを書き換えて他の組織になりすませる状態でした。
AIだけでは防げなかった理由:PostgreSQLの公式ドキュメントでは、UPDATEのポリシーは、USINGが更新対象にできる行を、WITH CHECKが更新後の行として保存してよいかを決めます。USINGだけを書くと同じ式が両方に使われるので、「自分の行か」だけを書いたポリシーは、更新後の組織IDに何の条件もかけません。
ポリシーは存在し、RLSも有効なので、有無を見るだけの確認は通ってしまいます。
人がしたこと:全テーブル・全ポリシーに、必要なUSINGとWITH CHECKが揃っているかを項目ごとに確認しました。組織IDのように変えてはいけない列は、DBのトリガーでも更新を禁止し、管理者権限の経路でも通らないようにしました。
事故4:開発環境が、管理者権限で動いていた
起きたこと:ローカル開発では、ログインを省略する設定が有効で、DBに管理者権限(service_role)で接続していました。そのため権限の漏れ2件が本番まで通りました。
1件は、送信者マスタのテーブルでRLSを有効にしたままポリシーを1本も作らず、本番で追加も一覧も全拒否になったもの。もう1件は、排他制御の関数を管理者にしか実行許可せず、送信モードが一度も動いていなかったものです。
1人で使っても全候補者に「他のメンバーが対応中です」と出ました。
AIだけでは防げなかった理由:Supabaseの公式ドキュメントによると、service_roleはRLSを迂回します。一方、RLSを有効にしてポリシーがなければ、公開キーのAPIからはデータが一切見えません。
手元ではどちらも成功するので、テストも画面確認も通ります。「手元で動いた」が、確認の根拠になっていました。
人がしたこと:本物のユーザーのセッションを発行し、画面と同じ権限(authenticated)でRPCやSELECT、INSERTを実行する検証に切り替えました。監査も、叩けてはいけない関数が増えていないかだけでなく、叩けるべき関数が叩けるかまで見るようにしました。
事故5:ログインを長持ちさせる修正が、ログアウトを壊した
起きたこと:ログインを長持ちさせるため、セッションCookieの有効期間を一律に最低30日へ底上げしていました。のちに「しばらく使うと勝手にログアウトされる」という報告が出て、原因がこの底上げだと分かりました。
AIだけでは防げなかった理由:Supabaseの認証ライブラリはCookieを消すとき、有効期間を0にして伝えます。MDNによると、Max-Ageが0または負の値だとCookieは即座に失効します。
底上げはこの削除の合図まで30日保持に変えていました。セッションは文字数に応じて複数のCookieに分割され、分割数が減るときに古い分が残って読み取りを壊します。
書き込みの確認は成功するので、この条件でしか出ない失敗には届きません。
人がしたこと:削除はそのまま通し、底上げは書き込みのときだけにしました。検証は「期限切れのセッションと古い分割Cookie」を付けたリクエストで行いました。
セッションが有効なままだと書き込みが起きず何も確かめられません。ビルドし直す前に測り、古いコードを検証して一度誤判定もしました。
コードの外にあった前提:実行環境の事故
次の3件は、コードを読んでも原因が見つかりません。原因はコードの外、実行環境の決まりごとにありました。
事故6:ページが1秒近くかかる、原因はクエリではなかった
起きたこと:自社SaaSの求人一覧ページが1秒近くかかりました。DBクエリ1本ずつの計測は30〜40ミリ秒で、速い数字でした。
AIだけでは防げなかった理由:原因は2つの掛け算でした。
DBは東京にあるのに、Vercelの関数は新規プロジェクトの既定で米国のワシントンD.C.(iad1)で動いていました。公式ドキュメントにこの既定が書かれています。
往復のたびに太平洋をまたぎ、片道で90ミリ秒前後かかっていました。さらに一覧は、求人、生成結果、状態の順にDBへ3回、直列に往復していました。
クエリ単体の計測では、どちらも見えません。
人がしたこと:DBのIPアドレスからリージョンを判定し、設定で関数の実行場所を東京にしました。直列の往復を並列にまとめ、1回の処理で何度も走っていた現在の組織を取る処理を1回にしました(4回が1回)。
往復を減らす近道として認証の検証を省く案もありますが、速くなる代わりにセキュリティの変更になるので採りませんでした。
事故7:「TZを設定する」という手順が、実行できなかった
起きたこと:日程調整ツールの開発メモに「本番では TZ=Asia/Tokyo が必須」と繰り返し書いていました。実際にはVercelでTZは予約済みの環境変数で、使えません。
本番のままだと日付計算が9時間ずれ、候補枠の時刻が丸ごとずれるところで、公開前に気づきました。
AIだけでは防げなかった理由:手元のJSTで試すと、すべて正しく動きます。メモの文面ももっともらしく、読んでも違和感がありません。
AIと進める作業では、メモに書いた前提が次の作業の前提になります。予約済み環境変数の一覧は、コードの外の公式ドキュメントにありました。
人がしたこと:日付の計算を実行環境のタイムゾーンに頼らず、UTCの取得関数に9時間を自分で足す形に統一しました。表示はサーバー側で「Asia/Tokyo」を指定して文字列にしてから渡します。
検証はTZをUTC、Asia/Tokyo、America/New_Yorkの3つに変えて、同じ出力になるか見ました。手元だけで試すと通ってしまうためです。
事故8:Googleのクロールが、2日で止まった
起きたこと:約1.6万件のDBを持つ自社Webメディアで、Googleのクロールが1日620件前後から2日でほぼ0になりました。
AIだけでは防げなかった理由:詳細ページを1枚作るたびに、全件をDBから読み込む実装でした(1,000件ずつ17往復で、事故1の上限がここでは速度として現れました)。ビルド時に作ったページは速いので、普段の目視では気づけません。
作っていないページは、最初のアクセスで生成されます(Next.js公式のISRの説明)。その初回生成が15秒かかり、最初の訪問者になったGooglebotが待たされたと判断しました。
Googleの公式ドキュメントは、サイトの応答が遅くなったりサーバーエラーが続いたりするとクロール容量の上限が下がり、クロールが減ると説明しています。
人がしたこと:原因の切り分けを、Search Consoleの「検出 - インデックス未登録」ならクロール統計とホストのステータスを先に見る順にしました。実測は、作成済みページでなく未生成のページで行います。
一覧用の取得処理を詳細ページで使い回すのをやめ、単一取得は単一クエリにしました。直ったかどうかの判定は、表示回数でなくクロール統計の回復で見ます。
経験上、回復には数日から2週間ほどかかりました。
直したつもりで悪くなった:タイムアウトの事故
事故9:失敗を消したら、品質の劣化が見えなくなった
起きたこと:自社SaaSのスカウト文面の一括生成で、57件中8件が「時間内に終わらなかった」と失敗しました。最初の修正は「残り時間がなければ書き直しを飛ばす」でした。
失敗は止まりましたが、作り直した8本のうち7本に、使わせたくない定型句が残ったまま外に出ました。
AIだけでは防げなかった理由:「失敗をなくす」という依頼には、書き直しを飛ばす修正で応えられます。品質を守るという暗黙の条件は、依頼に入っていませんでした。
失敗は赤いエラーで見えますが、品質の劣化は見えません。1本あたりのAPI呼び出し回数が1.00回、つまり書き直しが一度も走っていないという数字を見るまで、直ったように見えていました。
人がしたこと:まず実測しました。1件は中央値で16〜18秒、最大33秒、書き直しを3回挟むと100秒で、枠は45秒でした。
処理を削らず、実行時間の上限を実測に合わせて上げました。Vercelの公式ドキュメントによると、関数の最長実行時間は設定でき、超えると打ち切られます。
裏で流す処理(Next.jsのafter)も、起動したページの最長実行時間の範囲で動くため、ページ側にも指定が必要です。品質を削る分岐を入れるなら、発動した回数を測れるようにし、直した後は出来上がった物を検査器にかけ直します。
9件から見える、残る仕事は5つの能力
9件に共通するのは、AIの出力を受け取った後に、何を、どこで、どう確かめるかが決まっていなかったことです。その決める仕事が、人に残りました。
- 境界条件を疑い、件数で確かめる(事故1・2):「全件のはず」「処理済みのはず」を、総数と一致で確かめる
- 本物の権限と経路で試す(事故3・4・5):管理者でなく、実際のユーザーの権限で、画面と同じ経路を通す
- 遅さや不具合を構造で切り分ける(事故6・8):個々の部品の計測ではなく、往復の回数と距離、クロールの統計など本番の観測から見る
- 実行環境と仕様の意味を知る(事故5・7):Max-Age=0が削除の合図であること、TZが設定できないことなど、コードの外の決まりごと
- 見えない劣化を測る(事故9・2):失敗は見えるが品質の劣化は見えないので、回数や一致率を測れる形にする
採用する側は、この力をどう見るか
キッカケクリエイションは2026年2月24〜27日、コードレビューを担当するITエンジニア322名にインターネット調査をしました。
AI生成コードのレビュー経験がある277名のうち、レビュー担当者の負担が増えたと答えたのは86.3%でした。レビューで見つかった問題で最も多かったのは、提出者本人がコードの内容を説明できなかったことで、49.5%でした(上位3つまでの複数回答)。
GoogleのDORAは2025年の報告書で、世界の技術職ほぼ5,000人の調査から、仕事でAIを使う人が90%に達する一方、AIはチームを直すのではなく、すでにあるものを増幅すると述べています。
AIが一般的になるほど、「AIで作れる」ことは差になりにくくなります。
見られるのは、AIが作ったものについて、何を確かめ、何が分かり、何を直したかを説明できるかではないでしょうか。ポートフォリオなら、動く画面の写真より、確かめたことの記録のほうが伝わりやすいと考えます。
今日からできること
AIで小さなものを作って公開したら、次の3つを自分で確かめ、READMEに「確かめたこと」として書いてみてください。
- 件数:DBやAPIから取得した件数が、総数と一致するか。取得した後に数える
- 権限:別のユーザーで本物のログインをして、見えてはいけないものが見えないか。見えるべきものが見えるか
- 本番:公開した環境で、手元と同じ結果か。日付、地域、環境変数、遅いページを見る
AIに指示するときは「何が起きたら失敗か」を先に書き、直した後は直った証拠も出させます。現役のエンジニアなら、チームのレビューで「何を確かめたか」を1行添える運用から始められます。
学ぶ順番の側から整理した記事は、プログラミングを学ぶ意味はAI時代にもあるかにまとめています。



