※この記事は、Claude Codeで1人開発しているSNS運用SaaS「ThreadPost」の開発日記です。
SNS運用を自動化しませんか?
ThreadPostなら、投稿作成・画像生成・スケジュール管理まで全てAIにお任せ。
終わらないタイムアウトとの戦い
非同期にした。同期に戻した。また非同期にした。
Claude Codeは僕のことで遊んでいるのかと思った。
4コマ漫画の生成機能を作っていた。
Vercelのタイムアウト画面を今日だけで50回は見た。
真っ白な画面に無機質な504エラーが表示される。
コードは完璧に書かれている。AIのロジックは間違っていない。
でも動かない。
インフラの制約という見えない壁に激突し続けた。
ローカルでは動くのに本番で落ちる。
開発者にとって一番胃が痛くなる現象だ。

50コミットで進捗ゼロの現実
今週の総コミット数は50件。
そのうち新機能のリリースは0件。
バグ修正とリファクタリングの山だ。
4コマ漫画をAIで自動生成する機能。たったそれだけを作るのに1ヶ月迷走している。
AIに任せればSaaSが1日でできる。
そんな幻想は今日で完全に終わった。
ロジックを書くのは一瞬だ。
でも、それを本番環境のサーバーレスアーキテクチャで動かすのは全く別の競技だ。
メモリ制限、実行時間の上限、コネクションの枯渇。
泥臭いインフラとの戦いがずっと続いている。

非同期化とインフラの迷宮
4コマ漫画を作りたい。
テキストから画像を4枚連続で生成する。単純な処理に見える。
でも裏側では重いAIのAPIを何度も叩き続ける。
最初はInngestというジョブキューを使って非同期化した。
ユーザーを画面の前で待たせないためのベストプラクティスだ。
でも画像がリアルタイムで表示されない。
画面のプログレスバーがピタッと止まる。
ユーザーは「生成中なのかエラーで止まったのか」全くわからない状態になる。体験として最悪だ。
僕は一旦、同期処理に戻した。
シンプルにAPIルートで待てばいい。そう思った。
甘かった。
Vercelのタイムアウトの壁が容赦なく立ち塞がる。
サーバーレス関数は無限に待ってくれない。
Hobbyプランなら10秒、Proプランでも最大5分が限界だ。
画像4枚の生成とDBへの保存。
5分以内に終わる保証なんてどこにもない。
案の定、途中で処理がぶち切られる。
インフラが落ちる原因は大きく3つあった。
- Vercelの実行時間上限(5分)の超過
- SupabaseのDB保存時のペイロード過大
- Inngestの同時実行数(Concurrency)の制限突破
しんたろー:
企業ならここでバックエンドエンジニアが3人出てくる。AWSのSQSとLambdaを組み合わせて、フロントエンドとはWebSocketでリアルタイムに繋ぐ。数週間かかる重厚なアーキテクチャ設計だ。僕はそれを1人で、しかも数時間でやろうとしている。無謀すぎる。
「fix: Vercel function timeout for Inngest manga generation」
VercelのmaxDurationを300秒に設定した。これで5分までは耐えられる。
でも根本的な解決じゃない。
しばらくしたら今度はSupabaseのDB保存でタイムアウトが起きた。
原因は画像の保存方法だ。
生成されたBase64の巨大な画像データを、そのままDBのレコードに突っ込もうとしていた。
数メガバイトの文字列をネットワーク越しに送れば、そりゃ詰まる。
一般的に、画像はAWS S3やSupabase Storageなどのオブジェクトストレージに置く。DBにはURLだけを保存するのが鉄則だ。
僕はService Roleクライアントを追加した。
RLS(Row Level Security)の制限をバイパスしつつ、URLだけを保存するように書き換えた。
これでDB側のネットワークの詰まりは解消された。
でも、フロントエンドの「待たされている感」は消えない。
「直したって言うな。動いてないんだから」
Claude Codeのターミナルに向かって何度呟いたかわからない。
「feat: 漫画パネル画像生成をInngest+ポーリング方式に変更」
結局、非同期処理とポーリングの組み合わせに落ち着いた。
バックグラウンドでInngestが画像を1枚ずつ生成する。
フロントエンドは3秒に1回、DBに「終わった?」と聞きに行く。
「feat: ストーリー生成のStage 1-3進捗をUIに詳細表示」
待っている間も退屈させない工夫を入れた。構成、セリフ、シーン詳細の進捗メッセージを画面に出す。
「fix: 漫画生成ダイアログを閉じてもポーリングを継続するよう修正」
ダイアログを閉じても、裏で生成が続くようにした。
「feat: 投稿候補画面に漫画生成の進捗バナーを追加」
進捗バナーも画面の端に出した。
非同期と同期の間を何度も往復して、ようやく「普通に動く」状態になった。
AIは綺麗なコードを書いてくれる。
でも「VercelとSupabaseとInngestをどう組み合わせれば破綻しないか」という構造は、僕が設計するしかなかった。
しんたろー:
Claudeに「タイムアウトを直して」と投げると、設定値をいじるだけの対症療法しか出てこない。maxDurationを60→120→300と3回変えた。全部Claudeが書いた。でも「そもそもBase64をDBに突っ込むな」という判断は僕がした。タイピングは速い。設計はしない。
キャラクター一貫性の迷宮
インフラの壁を越えたら、次はAIモデルの機嫌取りだ。
4コマ漫画の命はキャラクターの一貫性。
1コマ目と2コマ目で主人公の顔が変わったら、それはもう漫画として成立しない。
最初は、登場する全キャラクターの参照画像をAIに毎回渡した。
「この4人の設定を全部守って描いてね」という指示だ。
結果は悲惨だった。
サトシの顔にアイコの髪型が乗った、謎のキメラキャラクターが爆誕した。
画像生成AIが混乱するパターンも明確になった。
- 全キャラクターの画像を一度に渡す
- 前のコマの画像を背景ごと渡す
- 喜怒哀楽の激しい表情をベース画像にする
- 複数の異なる画風の画像を同時に参照させる
AIのコンテキストウィンドウには限界がある。
画像という重い情報量が多すぎると、AIはパニックを起こす。
「feat: 4コマ漫画生成で前のコマ画像を参照として追加」
直前の絵を見ながら描けば、自然な連続性が出るはずだ。これも見事に失敗した。
画像生成AIに前の画像を渡すと、キャラクターだけでなく背景のノイズまで引き継いでしまう。
コマを進めるごとに、背景のディテールがどんどん歪んでいく。
4コマ目には、謎の異空間でキャンプをするキャラクターが出来上がっていた。
「fix: 4コマ漫画生成で登場キャラクターのみの参照画像を渡すように戻す」
結局、一番シンプルな方法に戻した。
そのコマに登場するキャラクターの画像だけを厳選して渡す。AIへの余計なノイズを極限まで減らす作戦だ。
しんたろー:
参照画像を4枚→1枚に減らしたら、キャラクターの顔がやっと安定した。情報を足せば足すほど崩れる。3回試して3回失敗してから気づいた。最初から引き算で考えればよかった。たぶん。
「feat: shintaro基準でキャラ参考画像を統一再生成」
スタイル参照を1枚の画像に絞った。複数の画風を混ぜると、AIがどっちに寄せるべきか迷う。
だから手書きノート風の1枚だけを基準にした。
「feat: キャラクターv6(イラスト調ベース立ち絵)追加」
ニュートラルな表情のベースキャラデザを作った。
喜怒哀楽の激しい画像を参考に渡すと、AIは常に怒った顔を描いてしまう。
無表情の立ち絵を渡して、プロンプトで表情を後付けする。
「refactor: 台本データをJSON外部ファイルに分離」
漫画のセリフや構成をコードから分離した。
コードの中に日本語の長文が混ざると、AIがコードの構造を理解しにくくなる。
データとロジックの分離。基本中の基本だけど、AI開発でも超重要だった。
ボタンを押したら面白い4コマ漫画がサクッと出てくる。それだけを実現するために、参照画像の渡し方を3回変えた。
ここまで読んだあなたに
今なら無料で全機能をお試しいただけます。設定後は完全放置でプロ品質の投稿を毎日生成。
落とし穴
Inngestで非同期にしたのに、Vercelのタイムアウトにやられた。
さらにInngestのconcurrency制限にも引っかかった。
「fix: Inngestのconcurrency上限をプラン制限(5)に合わせる」
無料プランの制限を超えてジョブを詰め込み、勝手に自滅していた。
結局同期に戻したら、今度はDB保存でタイムアウト。
何が正解かわからなくなった。
「直したって言うな。動いてないんだから」って何回思ったかわからない。
AIにコード書かせても、インフラの壁はAIじゃ壊せない。
僕が構造を決めるしかなかった。
次からはインフラの制約を先に調べてからAIに投げる。たぶん。
数字で振り返るインフラ格闘
今週の格闘を数字でまとめた。
| 項目 | 今週の数字 | 比較対象 |
|------|------------|----------|
| 総コミット数 | 50件 | 先週の新機能は3件 |
| 新機能リリース | 0件 | バグ修正3件 |
| 非同期化の実装・デバッグ時間 | 約1時間45分 | 企業チームなら2〜3週間 |
| Vercel Max Duration | 300秒 | Hobbyプランは10秒 |
| Inngest Concurrency | 5 | 以前の設定は10 |
| 参照画像の渡し方の変更回数 | 3回 | 正解は1枚に絞ること |
非同期処理の実装とデバッグにかかった時間は約1時間45分。
企業でバックエンドとフロントエンドのチームが連携して同様のシステムを構築するなら2〜3週間かかると言われている。
1人で全てを触れるフルスタック開発と、Claude Codeのコーディング速度が合わさった結果だ。
ただし、UIはボロボロだった。進捗バナーのデザインは後回しにした。
3秒に1回のポーリングは、今のところ動いている。
でも、ユーザーが100人同時に漫画を生成し始めたらSupabaseのDBコネクションが枯渇して、サービス全体が落ちる未来が見える。
WebSocketへの移行は、まだ先の話になりそうだ。
よくある質問
Q. Inngestのconcurrency制限に引っかかったとき、具体的に何が起きたの?
ジョブが5件を超えた瞬間、新しいジョブがキューに積まれたまま実行されなくなった。
フロントエンドはポーリングし続けるが、バックグラウンドでは何も動いていない状態だ。
ダッシュボードのInngest管理画面で「Throttled」ステータスを確認して初めて気づいた。
Q. Vercelのタイムアウトを300秒に伸ばしても根本解決にならない理由は?
画像4枚の生成時間はAI側のレスポンス次第で変動する。
混雑時には1枚あたり90秒以上かかることもあり、4枚で300秒を超えるケースが普通に発生する。
だからInngestで非同期化して、Vercelの実行時間から切り離す構造が必要になった。
Q. 企業開発と個人開発で、非同期処理のアプローチはどう違う?
企業ならAWS SQS、EventBridge、Redisなどを組み合わせた堅牢なインフラを数週間かけて構築する。
個人の場合はInngestやUpstashなどのマネージドサービスを使い、数時間で立ち上げるのが主流だ。
スケーラビリティよりも、開発スピードと保守のしやすさを最優先する。
泥沼の先に見えた景色
インフラの壁に何度も跳ね返されたけど、なんとか4コマ漫画は動くようになった。
次の壁はコネクション枯渇だ。たぶん。

この記事が参考になったら、ThreadPostを試してみませんか?
投稿作成・画像生成・スケジュール管理まで、全てAIにお任せできます。
ThreadPostをもっと知る