“プロダクションで動作する” — これは、ステージングやローカルマシンではエラーが安定して再現するにもかかわらず、プロダクションではバグが再現しない場合に開発者が言うフレーズです。問題のほとんどは常に環境の不一致が原因です:依存関係の異なるバージョン、設定ファイル、データベースの状態、サーバー設定など。Stack Overflow Developer Survey 2024の分析によると、開発者の43%が少なくとも月に一度、コードがローカルマシンでは動作するがプロダクションでは落ちる状況に直面しています。この不一致がなぜ発生し、どう防ぐかを解説します。
重要なポイント
“プロダクションで動作する” — これは開発者の間で定着した表現で、コードがプロダクションサーバーでは機能するが、テスト環境や同僚のローカルマシンでは動作を拒否する状況を指します。表面的には「問題なし」に聞こえますが、実際には問題があります — 単にプロダクション環境で再現しないだけです。不一致の根源は環境間の設定、バージョン、データの違いです。
このフレーズは別の有名な言い訳「ローカルでは動作する」の対極として生まれました。開発者が「ローカルで動作する」と言えば、バグは他の人にしか存在しません。そして「プロダクションで動作する」なら — バグはステージングかテスト環境にのみ存在し、プロダクションは正常です。皮肉なことに、どちらの場合も問題は現実であり、単に見ている人に現れていないだけです。DevOps Research and Assessment (DORA) 2023の調査によると、デプロイ自動化のレベルが高いチームは、このような不一致に3倍遭遇しにくいです。
ビジネスの観点から見ると、「プロダクションで動作する」状況は見た目よりも危険です。ステージングにバグがあってもプロダクションにない場合、開発者はそれを無視する可能性があります — そして次のデプロイでエラーがプロダクションに移行します。一時的な安心は将来の問題になり、ユーザーからのプレッシャーのもとで修正しなければならなくなります。
このフレーズが定着した心理的理由は防御反射です。ステージングでバグを見てもプロダクションでは見ない開発者は、無意識に問題を過小評価する可能性があります:「プロダクションで全て大丈夫なら、緊急ではない」。古典的な認知バイアス — 生存者誤差で、プロダクションの目に見える成功が将来の障害の潜在的脅威を上回ります。
第二の理由は曖昧な責任です。プロダクションが動作しステージングが動作しない場合、コードではなく環境が悪いことになります。開発者はバグの責任を自分から外し、DevOpsエンジニアや管理者に転嫁します。Atlassian State of DevOps 2022によると、統一されたデプロイ環境(Docker、Kubernetes)のないチームでは、このような責任転嫁が60%多く発生します。
第三の理由はゼロダウンタイムリリースへの恐れです。開発者がステージングのバグを修正して修正をデプロイする場合、再びコードレビュー、テスト、デプロイが必要になります。「プロダクションで動作する」というフレーズで次のリリースまで修正を先延ばしにでき、現在の負荷を減らせます。先延ばしにされた修正は、チームにおける技術的負債蓄積の主な原因の一つです。
プロダクションとステージングは決して完全に同一にはなりません — 規模、負荷、データの違いにより技術的に不可能です。しかし、主要なパラメータは一致すべきです:オペレーティングシステムのバージョン、コンパイラ、インタプリタ、データベース、ウェブサーバー、プロジェクトのすべての依存関係。一つでもパラメータが異なれば — コードの動作が変わる可能性があります。
環境間の主な違いは次のとおりです:
コンテナ化はこれらの問題の大部分を解決します。プロダクション用にビルドされたDockerイメージはステージングでも使用されるべきです。唯一の違いは環境変数とボリュームマウントです。Docker State of Application Development 2023によると、全環境で統一イメージを使用するチームは不一致の数を74%削減します。
| パラメータ | ローカル環境 | ステージング | プロダクション |
|---|---|---|---|
| OS | macOS / Windows | Linuxサーバー | Linuxサーバー |
| データベース | SQLite / ローカルMySQL | MySQLクラスター | レプリケーション付きMySQLクラスター |
| 負荷 | 1ユーザー | 10–100のシミュレーション | 1000+の実ユーザー |
| データ | フィクスチャ | マスク済み | 実データ |
| CDN / キャッシュ | なし | 部分的 | 完全 |
最初で最も一般的な原因は依存関係の異なるバージョンです。開発者はローカルで--saveフラグ付きでパッケージをインストールしますが、package.jsonやlockファイルの更新を忘れます。プロダクションへのデプロイ時に異なるバージョンがインストールされ、異なる動作をします。npmエコシステムではlockファイルが完全に問題を解決し、他のパッケージマネージャーでも同様のメカニズム(Gemfile.lock、Podfile.lock、pubspec.lock)があります。
第二の原因は欠落または余分な環境変数です。開発者はローカルマシンで.envファイルを使用しますが、CI/CDパイプラインやサーバーに対応する変数を追加しません。結果 — コードがAPIやデータベースへの接続エラーで失敗します。GitLab DevSecOps Survey 2023によると、プロダクションでのインシデントの27%が誤った環境変数に関連しています。
第三の原因はデータベースの状態です。ステージングのデータベースにはプロダクションにないレコードがあったり、逆にマイグレーションが不足していたりします。典型的なシナリオ:開発者がテーブルの新しいフィールドを扱うコードを書くが、マイグレーションがまだプロダクションに適用されていない。後方互換性のあるマイグレーション戦略がこのような状況を避ける唯一の方法です。
第四の原因は地域と言語設定です。日付形式、小数の区切り文字、テキストエンコーディング — これらはすべて開発者のローカルマシンとサーバーで異なる可能性があります。国際化プロジェクトで特に重要です。解決策 — アプリケーション設定でロケールを明示的に指定し、システム設定に依存しないことです。
最初のステップ — 両方の環境のログを比較すること。ログレベルの違いが原因を隠すことがよくあります:プロダクションではINFOが有効で、ステージングではDEBUGの場合があります。同じログレベルを設定し、両方の環境が機械比較可能な形式で書き込むことを確認してください。集中ログ収集システム — Sentry、Datadog、ELK Stackを使用しましょう。
第二のステップ — 依存関係のバージョンを確認すること。lockファイルを比較し、両方の環境でインストールされているパッケージのリストを表示します。マイナーまたはパッチバージョンの違いが不一致の最も可能性の高い原因です。npm ls、pip freeze、mvn dependency:treeなどのツールが素早く不一致を特定するのに役立ちます。
第三のステップ — プロダクション環境をローカルで再現すること。Docker Composeまたは類似のツールを使用してプロダクションインフラの正確なコピーを立ち上げます。ローカルコンテナでバグが再現すれば — 問題はコードにあり、環境ではありません。再現しなければ — 設定の違いを探します。
第四のステップ — フィーチャーフラグとA/Bテストを確認すること。プロダクションでは誤ったフラグが有効なため、コードが別のモードで動作している可能性があります。LaunchDarkly State of Feature Management 2023によると、プロダクションでの予期しない動作の最大40%が誤ったフィーチャーフラグの値に関連しています。全環境の統一フラグマニフェストがこの問題を解決します。
防止の主要ツールはInfrastructure as Code(IaC)です。すべての環境はコードで記述されるべきです:Dockerfile、docker-compose.yml、Terraformスクリプト、Ansibleプレイブック。サーバーへの手動変更は禁止 — 設定の変更はすべてリポジトリとコードレビューを通じて行われます。これにより、すべての環境が同一の設定を持つことが保証されます。
二番目に重要なツールは統一CI/CDパイプラインです。同じビルド、テスト、デプロイスクリプトがすべての環境で使用されるべきです。違いはターゲット変数(URL、キー)のみです。ステージングとプロダクションのパイプラインがステップで異なる場合 — 不一致は避けられません。
三番目のツールは自動データ同期です。定期的に(1日1回またはスケジュールに従って)プロダクションデータベースの匿名化コピーでステージングを更新します。これにより、合成フィクスチャではなく実データでコードをテストできます。ツール:PostgreSQL用pg_dump/pg_restore、MySQL用mysqldump、DataGripのような専門サービス。
四番目 — 不一致の監視。ステージングとプロダクションの差異が検出された場合のアラートを設定します。設定ファイルのハッシュやインストール済みパッケージのバージョンを比較する単純なスクリプトで、デバッグの時間を節約できます。予防は常に診断より安価です:環境の不一致を防ぐことは、「プロダクションで動作する」バグの原因を探すより少ない労力で済みます。
よくある質問
最初のケースではバグがステージングで見えるがプロダクションでは見えません。二番目のケースでは — 開発者以外の全員にバグが見え、その開発者のコードはローカルで動作します。共通の根源 — 環境の不一致ですが、状況は異なる段階で現れます。
ステージングのバグは、次のデプロイで既にプロダクションに移行する準備ができているバグであることを示してください。今の修正は、ユーザーからのプレッシャーによるホットフィックスよりも安価です。プロジェクトの歴史から例を挙げてください。
DORA 2023のデータによると、プロダクションでのインシデントの約25–30%が環境間の違いによって引き起こされています。コンテナ化のないチームではこの指標が50%に達します。コンテナ化により10–15%に低下します。
はい、これは一般的な原因の一つです。プロダクションではCDN、Varnish、Redisキャッシュが有効で、ステージングでは無効です。バグがキャッシュデータの配信に関連している場合、ステージングで現れ、プロダクションではキャッシュに隠されます。
Dockerはすべての段階(開発、テスト、ステージング、プロダクション)で環境の同一性を保証します。イメージが一度ビルドされてどこでも使用されれば — バージョンや設定の不一致は排除されます。統一イメージはデプロイの再現性の基盤です。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。