外部サービスからの応答が返ってこない画面を前に、待ち時間の設計をノートに書き出して考え直している開発者

AIに外部API連携の設計を相談する|タイムアウトと障害の詰め方

「決済のAPI、つないでおいて」

そう言われて、AIに聞きながら書いてみる。SDKの入れ方も、リクエストの組み立ても、レスポンスの受け取り方も、驚くほど早く出てくる。動かしてみたら、ちゃんとつながる。ここまでは、本当に速くなったと思います。

怖いのはそのあとです。相手のサービスが落ちた日、あるいは、落ちてはいないけれどやたらと遅い日。そのとき自分のシステムがどう振る舞うかは、つないだ日には誰も見ていません。

結論:外部API連携をAIに相談するときは、「つなぎ方」ではなく「つながらなかったときの振る舞い」を先に決めると、あとで慌てずに済みます。順番はこの4つです。①時間切れ(タイムアウト)を必ず自分で数字にする——書かないと「永遠に待つ」になっている言語・ライブラリがあります。②やり直し(リトライ)は、やり直してよい操作かどうかを先に仕分ける。③相手が明らかにおかしいときは遮断する(呼ぶのをいったんやめる)。④遮断している間、利用者に何を見せるかという代替を決める。そして最後に、この4つを決めた前提としてAIに渡してから、コードを書かせる。

一度に全部やらなくて大丈夫です。今日は、いま動いている連携をひとつ選んで、タイムアウトの秒数がコードのどこに書いてあるかを探すだけでも十分です。見つからなかったとしたら、それが今いちばん価値のある発見です。

なぜAIの連携コードは「つながるけれど落ちる」のか

まず、いま何が起きているのかを整理させてください。

AIに「この外部APIとの連携を書いて」と頼むと、返ってくるのは基本的にうまくいく道すじ(ハッピーパス)のコードです。リクエストを送り、200が返り、JSONを読む。これは間違いではありません。公式ドキュメントのサンプルが、まさにその形で書かれているからです。学習しているものがそうなっている以上、頼まれた範囲で最も自然な答えがそれになります。

一方、実際の運用でつまずくのは、ドキュメントのサンプルに載っていないところです。

最後のものが、いちばん厄介です。「失敗した」と思ってもう一度呼ぶと、相手側では二重に処理されます。

そしてもうひとつ。AIは、あなたが呼ぼうとしている相手がどういう性格のAPIかを知りません。「呼び直しても安全なのか」「1分あたり何回まで許されるのか」「落ちたとき、業務を止めてよいのか」。この3つは、相手の仕様書とあなたの業務にしか書かれていない情報です。渡していないものについて、AIは無難な一般論を返すしかありません。

つまり、生成されたコードが浅いのではなく、渡した前提が浅い。ここを分けて考えると、次にやることがはっきりします。

相手が返ってこないときの、4つの手当て

順番に見ていきます。この4つは重なっていて、上から順に効いてきます。

外部APIが応答しないときの対応を左から順に4段階で並べた図
外部APIが返ってこないときは、この順で手当てを考えると抜けが見つけやすくなります。

1. 時間切れ(タイムアウト)——待つ上限を、自分で数字にする

いちばん先に決めるのはこれです。理由は単純で、書かなければ「待ち続ける」ままの道具が多いからです。

たとえばPythonのrequestsは、timeoutを渡さない限り応答を待ち続けます。JavaScriptのaxiosも、初期値は「上限なし」です。言語やライブラリによって初期値はばらばらなので、いま使っているクライアントの初期値を一度だけ調べておくのが確実です。ここは、AIに「このライブラリのタイムアウト初期値は?」と聞くより、公式ドキュメントを見たほうが速くて確かです。

決めるのは、ざっくり2つの数字です。

「何秒がいいですか」に唯一の正解はありません。目安として、利用者が画面の前で待っている処理なら、その画面が許せる待ち時間から逆算する。夜間バッチのように誰も待っていない処理なら、もう少し長くてもかまいません。大事なのは秒数の正しさより、「無限に待つ」を消しておくことです。

なお、外側から順に呼び出しが重なっている場合(画面 → 自社API → 外部API)、内側のほうを短くしておくと、外側が先に諦めて内側だけ残る、という宙ぶらりんを避けられます。ここは図に書き出すと一発で分かります。

2. やり直し(リトライ)——やり直してよい操作かを、先に仕分ける

タイムアウトを入れると、次に「じゃあ、もう一回呼べばいいのでは」となります。半分正解です。

先に仕分けたいのは、その操作をもう一度呼んで安全かです。安全なものを 冪等(べきとう) と呼びます。何回呼んでも結果が同じになる、という性質のことです。

後者をどうしても再送したいときは、相手のAPIが「同じ依頼だ」と気づける仕組みがあるかを仕様書で確認します。多くの決済系APIには、こちらで採番したキーを添えると二重処理を防いでくれる仕組み(冪等キー、Idempotency-Keyなど呼び方はさまざま)があります。あるなら使う。ないなら、再送は自動ではなく人の判断に回す。この判断は、AIではなくあなたの側にあります。

やり直す回数と間隔にも、ひとつだけ気をつけたいことがあります。相手が重くなっているときに、全員が一斉に、しかも等間隔で再送すると、相手はさらに重くなります。 回数は2〜3回まで、間隔は少しずつ広げる(1秒 → 2秒 → 4秒。これを指数バックオフと呼びます)。そこにばらつき(ジッター)を少し足すと、再送のタイミングがそろわずに済みます。

そして、429(レート制限)が返ってきたときは、待ち時間の指定(Retry-Afterヘッダ)があればそれに従う。相手が「これくらい待って」と教えてくれているのに、自分の都合で早く叩き直すのはもったいない話です。

3. 遮断——明らかにおかしいときは、呼ぶのをいったんやめる

やり直しを入れても、相手が数分単位で落ちているときは、こちらの処理がずっと詰まったままになります。待って、やり直して、また待つ。その間、こちらのスレッドや接続はふさがれています。

そこで、一定の割合で失敗が続いたら、しばらく呼びに行くのをやめるという考え方があります。ブレーカーを落として、少し経ったら1本だけ試して様子を見る。うまくいったら元に戻す。サーキットブレーカと呼ばれる仕組みです。

ライブラリを入れるほどではない規模なら、簡易版でも意味があります。「直近の失敗が続いたら、次の1分間はこの連携をスキップして、代替の動きに切り替える」。それだけでも、相手の障害が自分のシステム全体に広がるのを止められます。

ここはAIが得意な相談相手です。「この処理で使えるサーキットブレーカの最小構成を、依存を増やさずに書くとどうなるか」と聞けば、たたき台は出てきます。そのたたき台を、自分の運用に合うか読んで直すのが人の仕事です。

4. 代替(フォールバック)——遮断している間、何を見せるか

ここが、いちばん後回しにされがちで、いちばん効くところです。

外部APIが返らなかったとき、利用者の画面には何が出るのか。真っ白なエラー画面なのか、「ただいま混み合っています」なのか、少し古いキャッシュのデータなのか、それとも「あとでメールでお送りします」なのか。

これは技術ではなく、業務の判断です。

AIにこの選択肢を出させるのは有効です。ただ、どれを選ぶかは、業務側の人と決める。「決済が通らないとき、注文を受け付けておいて後で処理していいですか」は、開発者だけでは決められない問いです。

AIに相談するときに渡す、5つの前提

ここまで決まったら、AIへの頼み方が変わります。「連携を書いて」ではなく、前提を添えて相談します。次の5つを箇条書きで渡すだけで、返ってくるものが実務に近づきます。

  1. 呼ぶ相手:APIの名前、公式ドキュメントの該当箇所(あれば貼る)、認証方式
  2. 相手の制約:レート制限の値、想定される応答時間、429やエラー時に何が返るか
  3. この操作の性質:やり直してよいか、冪等キーの仕組みがあるか
  4. こちら側の制約:利用者が待っている処理か/バッチか、許せる待ち時間、同時にどれくらい呼ぶか
  5. 落ちたときの方針:業務を止めてよいか、代替として何を見せるか

そのうえで、こう頼みます。

上記の前提で、この連携の失敗時の振る舞いを設計してほしい。タイムアウト、リトライ(回数・間隔・対象)、遮断、代替の4点について、選択肢と、それぞれで困る場面を挙げてください。決めきらず、判断が必要な箇所は「ここは業務判断」と明記してください。

「決めきらないで」と書いておくのが小さなコツです。AIは頼まれれば断言してくれますが、断言された数字をそのまま本番に置くのは、あなたが決めていないのと同じです。選択肢とトレードオフの形で出させたほうが、レビューにも説明にも使えます。

影響——ここを詰めておくと、どこが楽になるか

地味な作業に見えますが、効いてくるのは主に3つの場面です。

障害の夜。相手が落ちたとき、こちらが道連れにならない。「外部APIの障害で、該当機能だけ縮退しています」と言える状態は、「サービス全体が重いです」と言うしかない状態より、はるかに落ち着いて対応できます。

問い合わせの朝。「昨日の夕方、注文が通らなかった」と言われたとき、ログに「◯時◯分、外部APIがタイムアウト、3回再送して遮断、代替画面を表示」と残っていれば、調べる時間が数時間から数分になります。タイムアウトやリトライの記録は、必ずログに残す。ここは設計と同時に決めておきたいところです。

次の連携を作るとき。一度この4点を決めておくと、次のAPIでも同じ型で考えられます。チームの誰が書いても同じ構えになる、というのは、思っている以上に大きな財産です。

明日やること(3つだけ)

全部を一度にやろうとすると重いので、まずこの3つから。

  1. いま動いている連携をひとつ選んで、タイムアウトの秒数を探す。書かれていなければ、それが今日いちばんの収穫です。数字をひとつ入れるだけで、最悪の詰まり方がひとつ消えます。
  2. その連携が「やり直してよい操作か」を、一行メモする。冪等キーの仕組みが相手にあるかどうかも、仕様書で確認しておく。
  3. 落ちたときに利用者へ何を見せるかを、業務側の人にひとつ聞く。「もし外部が止まったら、待ってもらう/古い情報を出す/受け付けだけする、どれがいいですか」。この一問で、設計がかなり決まります。

チェックリスト(コピーして使えます)

AIに出させた外部API連携の設計・コードをレビューするときの確認項目です。一度に全部でなく、今日は使える所だけで十分です。

時間切れ(タイムアウト):

やり直し(リトライ):

遮断:

代替(フォールバック):

相手の仕様の確認:

AIへの渡し方:

最後に

外部API連携が難しいのは、腕の問題ではありません。自分では直せないものに、自分のサービスを預けているという、この仕事の構造そのものが難しいのです。相手がいつ落ちるかは分からないし、落ちたときに直せるのも自分ではない。

でも、預けたうえでできることは、思ったよりたくさんあります。待つ時間を決める。やり直す条件を決める。諦める線を決める。諦めたときに何を見せるか決める。どれも、相手が落ちても自分の側だけで完結する備えです。

外部サービスの障害が起きても機能が縮退して動き続けていることを、開発者と同僚が画面を見ながら確認して安心している場面

AIは、あなたの相手先がいつ落ちるかを教えてはくれません。でも、落ちたときの選択肢を並べることは得意です。前提さえ渡せば、抜けている観点を出してくれるし、たたき台のコードも書いてくれる。決めるところと、任せるところ。この線が引けていれば、AIは連携設計のいい相談相手になります。

今日は、タイムアウトの秒数をひとつ探すところから。数字がひとつ入るだけで、次に相談する内容はぐっと具体的になります。焦らず、一つずつでいきましょう。

よければ、こちらも

関連用語