はじめに
仮完成報告会の前日、本番環境でチームメンバーに触ってもらうためのデータ投入作業がありました。
見積もりは 1時間。
結果、8時間かかり、7時間の残業になりました。
補足しておくと、普段は月の残業が10時間を超えることもない環境です。今回もリーダーからは「明日の対応でもOK」と言われていましたが、土日前にバッファを確保しておきたくて自分の判断で残りました。とはいえまさかここまで長引くとは...
この記事では、そのとき何が起きたのか、なぜ防げなかったのかを振り返ります。同じような場面でハマる人が一人でも減れば幸いです。
前提
- チームで開発中のWebアプリケーション(Next.js + AWS Lambda)
- 普段のローカル開発ではseedファイルでデータを一括生成していた
- 今回は本番環境に手動でデータを投入する必要があった
6つの誤算
誤算は大きく3つに分類できます。
| 分類 | 誤算 |
|---|---|
| 本番環境特有のエラー | 誤算1:認証メール、誤算2:Lambda内エラー |
| ローカルで防げたはずのエラー | 誤算3:リダイレクト、誤算4:404、誤算5:メイン機能停止 |
| 焦りが招いた判断ミス | 誤算6:本番環境でのビルド |
誤算1:認証メールが送れない【本番環境特有】
状況
管理者アカウントのみCLIで作成し、チームメンバーのアカウントは管理者アカウントからGUIで作成する予定でした。ところが、別の機能でメール送信が動くことは確認済みだったにも関わらず、認証メールだけが本番環境で機能しませんでした。
原因
通知メールなど別の機能ではメール送信が正常に動作していたため、メール基盤自体には問題がありませんでした。しかし、認証メールだけが本番環境で送信されず、この時点では原因を特定できませんでした。「別のメールは送れている=メール機能は問題ない」という思い込みがあったぶん、認証メールだけ動かない状況に混乱しました。
解決策
根本原因の調査は後日に回し、CLIで「認証済み」の状態のユーザーを直接作成することで回避しました。報告会前のデータ投入が目的だったため、まずは先に進むことを優先した判断です。
誤算2:Lambda内でのライブラリエラー【本番環境特有】
状況
ファイルアップロード機能で、直前のcommitによりPDF解析ライブラリが pdf2json から pdfjs-dist に統一されていました。ところが、本番環境のLambda上でこの機能が動きませんでした。
原因
pdfjs-dist はブラウザのDOM API(DOMMatrix、Path2Dなど)に依存しており、これらが存在しないLambda(Node.jsランタイム)では動作しません。一方、変更前の pdf2json は純粋なNode.js実装のため問題ありませんでした。
解決策
pdf2json に戻すことで解決しました。
学び:Lambdaで動かすライブラリは「純粋Node.js実装かどうか」を確認する習慣が必要。 Issueやcommitの段階で気づけていれば、本番デプロイ前に対処できました。
誤算3:謎のリダイレクトが発生【ローカルで防げた】
状況
メイン機能にアクセスすると、無料プラン向けの機能制限画面にリダイレクトされました。有料プランの機能を使おうとしているのに、なぜ無料プランの画面に飛ばされるのかわからず混乱しました。
原因
アプリには組織ごとにサブスクリプション(プラン)を設定する仕組みがあり、プランが未登録の組織は無料プラン扱いとなって、メイン機能へのアクセスが制限される仕様でした。普段はseedファイルが組織作成時にプランも一緒に設定してくれていたため、「プランを手動で登録する」という手順の存在自体を認識していませんでした。
解決策
CLIで組織に適切なサブスクリプションを付与して解決しました。
誤算4:CloudWatchは200、でも画面は404【ローカルで防げた】
状況
アプリ内でリソースを作成する際、組織IDが必要です。この組織IDはユーザーが所属するチームテーブルを経由して取得されます。CloudWatch上のログは200を返しているのに、実際の画面では404が表示されるという状況でした。
原因
ユーザー作成時、組織への所属は必須ですが、チームへの所属は任意です。CLIでユーザーを作成した際にチームを設定しなかったため、組織IDを取得できず、リソースの参照で404になっていました。
解決策
先にチームを作成し、ユーザー作成時にチームにも所属させるようCLIコマンドを修正して解決しました。
誤算5:メイン機能が途中で動かなくなる【ローカルで防げた】
状況
メイン機能の序盤は正常に動作するものの、途中から動かなくなりました。
原因
メイン機能が途中から参照するテンプレートやフォーマットの設定データが、管理者アカウントから事前に登録されていませんでした。メイン機能の序盤はこれらのデータを必要としないため正常に動作しますが、処理が進むとテンプレートを参照するステップがあり、そこでデータが見つからずエラーになっていました。これもseedファイルでは自動生成されていた部分で、手動投入時に抜け落ちたものです。
解決策
管理者アカウントから必要なテンプレート・フォーマットデータを登録して解決しました。
誤算6:本番環境でビルドしてサーバーがダウン【焦りによる判断ミス】
状況
一連のエラー対応の中で、AIが「ビルドキャッシュが原因の可能性がある」と推測したものがありました。深く考えずに本番環境上で直接ビルドを実行したところ、メモリ不足でビルドが失敗し、サーバーがbusy状態になって一定時間操作不能になりました。
原因
現在のデプロイフローでは、ローカル(もしくはCI)でビルドしたものをECRイメージに含めてデプロイする構成になっています。本番環境のインスタンスはビルドを実行する想定のスペックではないため、メモリ不足に陥りました。
解決策
時間経過でサーバーが復旧するのを待ち、正規のデプロイフローで対応しました。
学び:焦っているときほど「これを実行したら何が起きるか」を考える。 本番環境で直接ビルドするという行為がなぜ推奨されないのか、知っていれば防げたミスでした。
すべてのデバッグを遅くした準備不足
6つの誤算に加えて、そもそもの準備不足がデバッグ全体を遅くしていました。それは lib/loggerによるログ出力がコード全体で統一されていなかった ことです。
ログ出力が統一されていないと、CloudWatchにログが出ていないとき、「ログ出力のコードが書かれていないからログが出ていないのか」「そもそもログ出力の処理まで到達していないのか」の切り分けができません。各誤算の原因調査のたびにこの問題が足を引っ張りました。
結局、作業の途中でコード全体に lib/logger を反映するPRを作成してデプロイすることになり、この作業とデプロイ待ちの時間も余計にかかりました。
学び:ログ出力の統一は、問題が起きる前にやっておくべきインフラ整備。 障害対応中にやることではありません。
なぜ防げなかったのか
6つの誤算とログの準備不足を振り返ると、根本原因は大きく4つに集約されます。
1. seedファイルへの依存
普段の開発ではseedファイルがデータの整合性を担保してくれていました。そのため「手動でデータを投入するときに何が必要か」を正確に把握できていませんでした。誤算3・4・5はすべてこれが原因です。
2. 本番環境特有の制約への知識不足
Lambda上ではブラウザのDOM APIに依存するライブラリが動作しないこと、本番インスタンスにはビルドを実行するだけのメモリがないこと。これらは知識として持っていれば事前に回避できた問題です。
3. ログ出力の未整備
lib/loggerがコード全体で統一されていなかったことで、エラーの切り分けに必要以上の時間がかかりました。ログは「問題が起きてから整備する」ものではなく、事前に統一しておくべきものです。
4. 焦りの中での「とりあえず試す」
残業が長引くにつれ、冷静な判断力が落ちていきました。「AIがそう言っているから一旦やってみよう」という脳死判断が、誤算6のサーバーダウンにつながりました。
次に活かすこと
- seedを使わないデータ投入パスをローカルで事前検証する。 本番に入れる前に、ローカルで同じ手順を踏めば誤算3・4・5は防げた
- Lambdaで使うライブラリは純粋Node.js実装かどうかを確認する。 ライブラリ変更のIssueやPRを見た時点でチェックする習慣をつける
-
ログ出力は問題が起きる前に統一しておく。
lib/loggerの導入漏れを放置しない。ログが揃っていればエラーの切り分けが格段に速くなる - 本番環境で「とりあえず試す」前に影響範囲を確認する。 特にビルドやマイグレーションなど、リソースを大きく消費する操作は慎重に
おわりに
ローカルで確認できる部分をちゃんとローカルで確認できていれば、少なくとも4時間は残業を減らせたはずです。
seedファイルは開発を便利にしてくれる一方で、手動オペレーション時に必要な手順を見えなくしてしまうという側面があります。「seedが何をやってくれているのか」を把握しておくことが、本番環境でのトラブルを未然に防ぐ第一歩だと痛感しました。
この失敗が、誰かの役に立てば嬉しいです。
株式会社シンシア
株式会社シンシアでは、実務未経験のエンジニアの方や学生エンジニアインターンを採用し一緒に働いています。
※ シンシアにおける働き方の様子はこちら
弊社には年間100人程度の実務未経験の方に応募いただき、技術面接を実施しております。
この記事が少しでも学びになったという方は、ぜひ wantedly のストーリーもご覧いただけるととても嬉しいです!