📚 経営目線のSaaS開発 シリーズ ①:コストと安全の線引き
はじめに
「ステージングは一段小さくていいですよね」
昔、インフラ担当から最初にそう提示されて、私はそのまま受け入れました。理屈は通っていましたし、安くなるのは事実です。
そして本番環境でだけ壊れました。ステージングでは何度やっても再現しない不具合が、顧客の目の前で出た。
以来、そう言われたときは「インフラ担当と一緒に話をさせてください」と頼むようにしています。私に削らない権限があるわけではないので、説得するしかありません。
ただ、この記事は「だから最初から全部揃えろ」という話ではありません。最小構成は目的ではなく、結果です。 コストを前提に、安全に設計していけば、結果として小さくなる。その順番は間違っていないと感じています。なので、そこを書いていきます。
書きたいのは いつ最終形としてSTGとPRDを揃えるか という一点です。
先に立場を明かしておきます。私はアプリケーション開発者で、インフラエンジニアとして実務に就いたことはありません。
この記事は、経営者でもある私が全体を見渡す必要に迫られて、アプリ専門でもインフラ専門でもなく、総合ディレクターとして全部やった人間の記録です。アプリ開発が専門の人間として、できる限りの最適解を考えてみました。
自社プロダクトでは技術判断と経営判断を同じ頭でやれるので、その点は特殊です。ただ、SESで客先に入れば上位の許可を得る必要があるので、そこは皆さんとまったく同じ立場です。
1. 昔はやらざるを得なかった
私がWebに触り始めた2000年頃、インフラエンジニアという職種はまだ一般的ではありませんでした。サーバがぽんと置かれて、「あとは全部やっておいて」でした。
OSも、ネットワークも、ミドルウェアも、アプリも、全部ひとりです。好きでやっていたわけではありません。 分けてくれる人がいなかっただけです。強制的に勉強せざるを得ませんでした。
いま考えると、サーバの設定にはかなり穴があったと思います。今ほどセキュリティに厳しくない、牧歌的な時代だったので許されていたのでしょう。
いまは違います。クラウドがあり、マネージドサービスがあり、専門の担当がいます。アプリ開発者がサブネットの設計を知らなくても、プロダクトは出せる。より一層高品質なサービスを提供できるようになって、本当に素晴らしい進化だと思います。
ただ、そのぶん失っているものもあると感じているので、そこを掘り下げました。
2. 分断されたのは、技術ではなく判断
開発を進めるにあたり、間違いなく言われる会話があります。
「STGは一段小さくていいよね」
このとき、それぞれの立場はこうなります。
- アプリ側は、その一段が何を意味するか判断できない。同時接続やメモリ挙動の差が、自分のコードのどこに出るのか見えない
- インフラ側は、そのアプリで何が本当に重いのか判断できない。どの処理が長時間ストリーミングするのか、コードを読んでいない
- 経営側は、安いことが正義なので、インフラ側を支持します
誰も嘘をついていません。それぞれの持ち場では正しい。
問題は、縦割りで統括されていて、誰も全体を見れていないことです。
そして厄介なのは、こういう構造から出てくる提案が、不安な気持ちから足し算に偏ることです。
たとえば、ALBのようなロードバランサーによるサーバの冗長化です。
「冗長化しましょう」は誰でも言えます。言っておけば、事故が起きた時に「私は進言しました」と言える。
一方「それはやりません。落ちたら数時間で戻します」は、落ちた時に自分が責められる宣言です。引き算は、リスクとメリットを明文化するところから資料を作り、説得しなければならない。手間でしかありません。
だから見積もりには足し算だけが並びます。そして経営側は、技術担当がそう言ったから、という責任を持たないまま承認することになります。
こうなると、問題が起きたときにできるのは叱責だけです。判断していないのだから、原因を切り分けようがない。考えてみれば当然のことです。
余談ですが、私はクラウドの場合、サーバが落ちるよりもクラウド全体が落ちるケースの方が多いと思っています。それを踏まえたうえで、ALBを含めたサーバ冗長化に月額で数万円をかけますか、という話をよくします。
クラウド時代になったのは、落ちた原因が「自社データセンターでの構築ミス」ではなく「クラウドが落ちた(=他社サービスが落ちた)」という言い訳にできるから流行った、という裏事情も散々聞いてきました。そこも考えてもらえると、少し気が楽になるかもしれません。
※ ハイアベイラビリティが必要なサービスは、その言い訳は止めてくださいね(笑)
3. 実際には、4段階で建てました
うちの構成は、こういう順で育てました。詳細は書けませんが、考え方だけ。
その前に、環境をいくつ持つかの話から。教科書的には DEV / STG / PRD の3環境です。開発用、検証用、本番用。
うちはクラウド上に3つ目を建てていません。 ひとりで開発しているので、複数人の作業が混ざることがない。ステージングを開発環境と兼用にすれば十分だ、と判断しました。
つまり、開発の場そのものがステージングです。手元のPCだけで進めるのは厳しかったので、ローカルは試作レベルにとどめています。
代わりに失ったものもあります。試作と検証が同じ場所になるので、「壊れている状態のステージング」が発生します。ひとりだから許容できるだけで、複数人なら成立しません。
そのうえで、段階はこうなります。
① ローカルで試作。クラウドには何も無い
② 本番環境と同等のステージングを構築。ここが開発環境そのもの
③ リリース直前。最終確認のため本番環境を建て、共通だったものを環境ごとに分離
④ 事業サイトなど、本体と無関係なものを切り離す
注目してほしいのは ② → ③ です。ここでコストが上がる方向に動かしています。
共通で1つ持っていたものを、環境ごとに2つに増やしました。節約の逆をやっています。
そして、この②から③のあいだで DR(災害復旧)をどう設計するか を決めています。ここは書くことが多いので、次回(シリーズ②)にまわします。
4. 同じ差分が、フェーズによって値段を変える
環境差分のコストは固定ではありません。
| フェーズ | 利用者数 | 差分が生む事故のコスト |
|---|---|---|
| リリース前 | 自分だけ | 安い。壊れても困るのは自分。直せばいい |
| リリース後 | 顧客がいる | 跳ね上がる。本番環境でだけ落ちる=信用が減る |
一般論としてはこうです。利用者が自分だけの間は、環境差分は安く済みます。
ただ、うちの場合は②の時点でステージングを本番環境と同等にしています。ここは一般論から外れるので、理由を書いておきます。
ステージングが開発環境そのものだからです。ここを小さくすると、開発で見ている挙動そのものが実態とズレます。「開発中は軽いから気づかなかった」を最初から抱え込むことになる。だから、ここだけは最初から落としませんでした。
そして③でリリース直前に本番環境を建てたとき、引き上げたのはステージングではなく、本番環境をステージングに合わせた形になりました。
もうひとつ大事なのは、リリースを境にステージングの役割が増えることです。
うちのステージングは開発環境を兼ねているので、リリース前は「作る場所」でした。リリース後もそれは変わりませんが、そこに稼働中の本番環境へ変更を当てる前の、最後の関門という役割が乗ります。顧客が使っている環境へ、そのまま流し込む手前の砦です。
本番環境と違う環境で検証しても、関門になりません。
だから「常に揃えろ」も「常に節約しろ」も間違いだと思っています。決めるべきは切り替え点をどこに置くかです。これは仕事の分担の話ではなく、設計のアイデアとして持っておく話です。
なお、切り替え点は「顧客が付いた瞬間」だけではありません。それはフェーズの区切りの一例にすぎない。この先には「顧客が何人を超えたとき」「同時アクセスが何を超えたとき」といった区切りも想定しておく必要があります。どこでフェーズを切るかを決めること自体が設計です。
ちなみに私はDB設計が専門なので、そちらの例で言うと——テーブル設計のときに「1レコードは100KB、1年間に見込まれる件数が3000、よって1年で300MB」といった見積もりをしていきます。そうすると、スケールアウトすべきタイミングが数字で見えてきます。同じ観点でフェーズを考えると、区切りが具体的になります。
5. それでも、本番環境でだけ壊れました
ただ、正直に言うと、揃えた後にも事故りました。
本番環境だけ、ある処理が長時間かかった末にタイムアウトする。ステージングでは何度やっても再現しない。同じコード、同じ構成、同じデータです。
原因は、本番環境とステージングで、外側の経路が違ったことでした。まったく同じにはセキュリティ上つくれなかったからです。ただ、逆に言えば問題の切り分けは非常に簡単でした。
- 本番環境は外部に公開しているので、前段に Cloudflare(ファイアウォールのようなもの)を通しています
- ステージングは内部から直接アクセスするので、そこを通りません
アプリが少しずつ返していた進捗が途中で溜め込まれ、Cloudflare側からは「長時間なにも返ってこない」ように見えて、タイムアウトで切断されていました。
直し方は単純で、前段にバッファさせないことを応答ヘッダで明示します。
X-Accel-Buffering: no
これを付けると、間に入るプロキシが「全部揃うまで溜める」のをやめます。少しずつ返しているのに前段からは無応答に見える、という誤認が止まります。ストリーミングを返す経路にだけ付ければ十分です。
ただ、問題は直し方ではありません。
「環境を揃えた」と言いながら、揃っていない層が残っていたことです。しかもこれは怠慢ではなく、構造上そこだけは統一できなかった。外部公開する本番環境と、内部からしか叩かないステージングでは、前段の経路が同じになりません。
なので、この記事で「全て揃えました」とは書けません。正確には、揃えたつもりでも、まだ揃っていない層がある。完全一致は原理的に不可能です。
だから、差分がどこに残っているかを知っていることの方が、揃っていること自体より重要だと思っています。
6. やらなかったこと と その理由
ここが本題です。足したものより、諦めたものの方が判断として重い。
| やらなかったこと | 理由 | 差額の目安 |
|---|---|---|
| マルチAZ/マルチリージョンのリアルタイム冗長 | ひとりで払える金額を超える。復旧目標を「数時間」に置き直して代替した | DBを冗長にするだけで月額はおおむね倍 |
| DEV環境をクラウドに建てること | ひとりなので複数人の作業が混ざらない。ステージングと兼用で足りる | 環境が1つ増えるぶん丸ごと |
| 外形監視を全環境に入れること | 本番環境だけで足りる。ステージングが落ちても誰も困らない | 監視対象の数だけ増える |
※金額は構成によって変わるので、目安として読んでください。
代わりに全振りしたのは「スムーズに作り直せること。ダウンタイムを限界まで抑えること」です。
- 構成はコード(Terraform/テラフォーム)で持つ
- データは定期的に外へ退避する
- 壊れたら直すのではなく、建て直して戻す
私はもともとエンタープライズのシステムを作ってきたので、DR(災害復旧)は必須という前提が体に入っています。ただ、当時のやり方をそのまま持ち込むと、ひとりでは確実に破産します。
だから RTO(復旧までの目標時間)は数分ではなく、数時間に置き直しました。 そこは諦めています。その代わり、いつでも作り直せる状態を維持している。
このあたりは書くことが多いので、次回(シリーズ②)でまとめて書きます。 ここでは「諦めた判断の一例」として置いておきます。
7. この構造の弱点
ここまで「ひとりで全部見ているから判断が速い」という話をしてきました。実際そうです。交渉相手がいないので、削る判断も足す判断も即決できます。
ただし、チェック機構がありません。
自分のドメインの外側にあるミスは、誰も指摘してくれません。私は業務知識に関わる誤りにはすぐ気づきますが、実装レイヤーの見落としは、AIを使った開発ということもあって通ってしまう確率が高い。速いぶん、盲点も検査されないまま本番環境に出ます。
分業には、遅くなる代わりに相互チェックが自動で入るという利点があります。ひとりでやるとそれが丸ごと消える。これは構造的な話で、気をつけて直るものではありません。
なので私は、AIを相談相手として置いています。 判断の理由を説明させ、反論させ、測ってから決める。それでだいぶ埋まりました。
そしてもうひとつ、冒頭に書いたとおり私は本職のインフラエンジニアではありません。
ネットワークエンジニアには憧れがあって、独学で勉強して半年ほど従事していたことはあります。ただそれは「やりたかったからやった」だけで、実務で(ネットワーク以外の)インフラを担当した経験はありません。この記事で書いた判断も、アプリ側から見た景色でしかない。専門家から見れば、見落としている層があるはずです。
だから正直に言えば、本来はインフラエンジニアがそこにいればいい話です。相談相手として、専門家に勝るものはありません。
まとめ
- ステージングを節約するのは、時期によっては正しい
- 最小構成は目的ではなく結果。前提にあるのはコスト
- クラウド上の環境は数を減らしてもいい。ただし失うものを自覚しておく
- 同じ差分が、フェーズによって値段を変える。利用者が自分だけの間は安い
- ただしステージングが開発環境を兼ねるなら、そこは最初から落とさない。開発で見ている挙動が実態とズレる
- リリースを境に、ステージングには関門という役割が増える
- 決めるべきは「揃えるかどうか」ではなく「いつ揃えるか」。切り替え点は複数ありうる
- 「揃えた」と言い切らない。構造上どうしても揃わない層がある
- 足したものより、諦めたものと理由を残す。それが次の判断材料になる
- ひとりで見ると速い。ただし相互チェックは失う
最後に:技術者同士、膝をつき合わせて話しませんか
昔は自分でやらざるを得ませんでした。いまは自分でやらなくてすみます。だから失うこともあります。
私が言いたいのは「全員がインフラをやるべきだ」ではありません。分業は合理的です。餅は餅屋で、それぞれの持ち場にはプロフェッショナルがいます。
問題は分業そのものではなく、縦割りのまま意見が交わらないことです。
アプリとインフラと経営判断が、それぞれ別の人の頭の中にあるとき、削る判断は誰にも出せません。出せるのは足し算だけになる。そして経営側は、責任を持てないまま承認することになります。
技術と経営が一体化することは稀です。ですが、技術どうしなら一緒に語れるはずです。私はそこを重要視すべきだと思っています。
もしお使いの環境で「ステージングは一段小さくていい」という話が出たら、一度膝をつき合わせて話してみてください。「その話し合いでどれほど双方の視界がクリアになり、どれほど自分たちのプロダクトに自信を持てるようになるか」を。
たぶん、どちらか一方では答えが出ません。出ないこと自体が、それぞれの限界を教えてくれます。
そして、それぞれのプロフェッショナルが率直に出し合った意見を、経営判断ができる人間のところへ持っていく。そこまでやれば、削る判断にも根拠が付きます。
縦割りをやめて、そこまで持っていければ、みんなが幸せになれると思っています。
※この記事の構成は、実際に運用しているサービスのものです。動いているものを見たい方はこちら。
→ https://dbv.co.jp/cnvskillsheetlp/?utm_source=qiita&utm_medium=article&utm_campaign=env_parity
📚 関連記事
📚 経営目線のSaaS開発(本シリーズ)
- コスト削減はどこまで妥当か — クラウド時代の安全との線引き(環境編) ← 本記事
📚 スキルシートと市場価値(別シリーズ)
同じプロダクトを、技術者本人の市場価値という角度から書いています。