ガイド

ローンチ後のSaaSを壊さずにスケールさせる方法

ローンチは簡単な部分でした。危険なのはその後の一年です。成長が、ここまで運んでくれたシンプルな製品を静かに壊していきます。これは、スローモーションの崩壊を避けてスケールするための、落ち着いた実践的なガイドです。

Have a nice dayHave a nice day読了 約3分
ローンチ後のSaaSを壊さずにスケールさせる方法

誰もがローンチを祝います。けれども、その後にやってくる部分について警告してくれる人はほとんどいません。最初の百人の顧客を獲得してくれた製品が、次の千人の重みでたわみ始める、あの奇妙で手に汗握る一年についてです。劇的なことは何も起きません。ただ、すべてが遅く、不安定に、変更しづらくなっていくのです。ある火曜日、かつて一日で済んだ機能に今は一週間かかると気づきますが、その理由を誰もはっきり説明できません。ほとんどのSaaS製品が静かに勝敗を分けるのは、ローンチではなく、まさにそこです。

私たちはまさにこの局面で、多くの創業者と向き合ってきました。彼らは失敗しているわけではありません。それが紛らわしいのです。売上は伸び、チームは大きくなり、デモもうまくいきます。けれども水面下で、製品はうめいています。サポートの問い合わせはユーザーより速く増えていきます。かつて退屈だったデプロイは、今や息を詰めて行うものになります。一年前は賢く感じられたコードベースが、今ではどの変更も別の何かを暴発させかねない地雷原のように感じられます。彼らは何も間違っていません。ただ、作ったものを成長で追い越しただけであり、それが本来起こるはずのことだと誰も教えてくれなかったのです。

ですからこれは、ひびが現れる前に、より多くの創業者に手にしてほしかったガイドです。ハイパースケールでも、Kubernetesでも、どこかのユニコーンが五千万ユーザー時にやったことの話でもありません。退屈で決定的な中間地点の話です。すべてを書き直したり、顧客を怖がらせたり、チームを燃え尽きさせたりせずに、少数に対して動くから多数に対して動くへ移ることです。目標は完璧なアーキテクチャではありません。静かに壊れ始める製品ではなく、成長し続ける製品です。

SaaSが成長するとき実際に壊れるもの

創業者を最も驚かせるのはこの部分です。スケールの問題が、身構えていた劇的な障害として現れることはほとんどありません。サーバーが燃え上がるわけではないのです。代わりに、製品は一種の微熱のようなものを発症します。即座に読み込めていたページが三秒かかり始めます。初期の顧客では問題なく動いていたレポートが、契約したばかりの大口顧客ではタイムアウトします。同じバグが何度も再発します。コードの二つの部分が、誰も文書化していない形でひそかに依存し合っているからです。

本当に壊れているのは、サーバーであることはまれです。それはあなたの前提です。初期には、最初のユーザーの形に合わせて作りました。少数のアカウント、小さなデータ、単純なワークフロー、誰もがほぼ同じ。成長は、同じものを増やすだけではありません。多様性を加えるのです。データが十倍ある顧客。想像もしなかった使い方をするチーム。全員が一斉にログインする月曜午前九時のスパイク。そのどれもが、破ることなど考えられなかった一年前にコードへ焼き込まれた前提を、静かに破っていきます。

製品が壊れるのは、ユーザーが増えたからではありません。それらのユーザーが、最初の顧客たちがそうだった以上に互いに異なっているから壊れるのです。
崩壊の局面で創業者に伝えていること

まず現れやすい四つの場所は予測可能です。データベースはほぼ常にカナリアです。小さなテーブルでは即座だったクエリが、データの増加とともに這うようになります。遅いエンドポイント。一つ二つのページがリクエストごとに過剰な処理をしており、トラフィックが積み重なるまでは問題ありません。もろいデプロイ。コードが絡み合いすぎて見通せず、何かをリリースすること自体が怖くなっています。そしてサポートの負荷。これはインフラとは全く別物ですが、製品が人々の実際の使い方にもう合っていないことを示す、最も正直な早期サインです。

数人の歩行者には問題なかった小さな木の橋が、増えていく群衆の下で目に見えて張り詰め、一枚二枚の板が曲がり始めている、落ち着いた抑えた色調の上品なエディトリアル風イラスト
スケールが失敗するとき、崩壊から始まることはまれです。たわみから始まります。新しい荷重ごとに、ほんの少しずつ曲がっていく一枚の板から。

まだ持っていない問題を解こうとする罠

修正の話をする前に、どんな最適化よりも多くの製品を救ってきた警告を一つ。成長中のSaaSにとって最大の脅威は、スケールを無視することではありません。早すぎる段階でそれを追いかけることです。創業者が最初の遅延を感じた瞬間、有名なエンジニアリングブログで読んだアーキテクチャに手を伸ばしたくなります。マイクロサービス。メッセージキュー。マルチリージョン構成。百万行も入っていないうちからのデータベースのシャーディング。

こうして、まだ到達していないスケールのためのインフラ構築に半年と大金を費やす一方で、肝心の製品は動かなくなります。さらに悪いことに、あらゆる将来の変更を難しくしてしまいました。分散システムは、手元にあったシンプルなものよりも、構築もデバッグも劇的に複雑だからです。まだ持っていなかった問題を、今日確実に抱える問題と引き換えにしたのです。何もリリースされない、という問題と。

ここでの規律は、そもそも良い製品を作るものと同じです。目の前の問題を解くこと。想像してうれしくなる問題ではなく。素早く変更できる、退屈でよく理解された一枚岩のほうが、触るのが怖い流行りの分散システムよりスケールします。複雑さは一度きりの買い物ではなく、毎日支払うコストです。

何かを変える前に計測する

この段階で出会うほぼすべての創業者は、問題の在りかを知っていると確信しています。その半分は間違っています。不注意だからではなく、直感がひどいプロファイラーだからです。遅く感じるコードの部分はたいてい問題なく、真犯人は、誰も思いもしなかったページで四十回走っている静かなクエリだったりします。計測していないものは直せません。そして当て推量こそ、チームが見当違いの最適化に何週間も費やす原因なのです。

始めるのに洒落た観測スタックは要りません。常に目の前に置く、退屈な三つの数字が必要です。どのエンドポイントが最も遅いか、そして実トラフィック下でどれほど遅いか。どのデータベースクエリが合計時間を最も食うか。単一で最も遅いクエリではなく、数千回の呼び出しで時間が積み上がるものです。そしてエラーが実際にどこで起きるかを、再現できるだけの文脈とともに。この三つがあれば、霧はたいてい一日で晴れます。

  1. 1
    基本的なモニタリングを有効にする
    エンドポイントごとの応答時間、エラー率、そしてデータベースのスロークエリログ。ホスティング型のツールなら一日の午後で済みます。見えない数字は改善できません。
  2. 2
    本当のワースト3を見つける
    勘ではなく、消費した合計時間で並べ替えます。三つの犯人がほぼ常に痛みの大半を占めます。書き留めてください。それが本当のロードマップです。
  3. 3
    一つ直して、もう一度計測する
    一つだけ変え、それから数字を再確認します。次へ進む前に効いたことを確かめます。一度に二つ変えれば、どちらが効いたのか決してわかりません。
  4. 4
    十分良くなったら止める
    始める前に「十分速い」を定義します。たとえば現在の負荷でどのページも一秒未満、というように。それを超えると、最適化は勝利ではなく時間の浪費です。

この最後のステップは見た目以上に重要です。パフォーマンス作業は本当に中毒性があります。削れるミリ秒は常にもう一つあるのです。けれども顧客は200ミリ秒と120ミリ秒の違いを感じませんし、それを追って費やす時間は、本当にビジネスを成長させる機能に使われなかった時間です。計測し、ワースト3を直し、勝利を宣言して、前へ進みましょう。

データベースはほぼ常に最初の壁

成長中のSaaSが最初の本当の天井にぶつかる場所に金を賭けるなら、私たちは毎回データベースに賭けます。それは、初期の小さな決定が最も激しく積み重なる、システムで唯一の部分です。インデックスのないクエリは、千行なら瞬きの間に走り、百万行で止まってしまいます。コードは変わっていません。変わったのはデータであり、データはただ増え続けるのです。

良い知らせは、データベースは最も安く、最も効果の高い修正が眠る場所でもあるということです。古典は欠けたインデックスです。たった一行が、数秒のクエリを即座のものに変えます。必要な数行を見つけるために全行を走査するのを、データベースがやめるからです。すぐ後ろにあるのがN+1クエリ問題です。一つの質問をする代わりに、同じ小さな質問を数百回ループで静かにデータベースへ投げるページです。どちらもよくあり、どちらも見るまで不可視で、どちらも見つけてしまえばたいてい一日の修正です。

ここには頼れる順序があり、終わりへ飛ぶより順番どおりに従うほうが得です。まずクエリを直します。インデックス、N+1、遅いレポート。次に、絶えず読まれるがめったに変わらないデータにキャッシュを足します。その後で初めて、リードレプリカ、より大きなインスタンス、データの分割を語る意味が出てきます。ほとんどのSaaS製品は後半のステップを必要としません。最初のステップをきちんとやる必要があっただけなのです。

司書が広大なインデックス付きの棚からラベルの貼られた一冊を即座に取り出すのと、床に並ぶラベルのない本を一冊ずつ必死に確かめる人物とを対比した、インデックスあり対なしのデータベースクエリを表すフラットなエディトリアル風イラスト
インデックスとは棚に貼られたラベルにすぎません。それがなければ、データベースはあなたが頼んだ一冊を見つけるために、床のすべての本を確かめます。

製品をスケールするとは、変更の仕方をスケールすること

創業者の不意を突く転換がこれです。ある点を越えると、スケールは製品がより多くのユーザーをさばくことではなくなり、チームがより多くの変更をさばくことになります。あなたと開発者一人だった頃は、誰もがシステム全体を頭に入れていました。何が影響を受けるか分かっていたので、何でも変えられました。五人十人になると、その心的モデルは砕けます。そして、全員が全部を知っている前提のコードは、負債になります。

デプロイが怖くなる本当の理由はこれです。コードが一夜にして悪くなったのではありません。変更の影響範囲を、もう誰も完全には予測できなくなったのです。解決策は英雄的な働きでもリリース凍結でもありません。大きくなったチームが互いの足を踏まずに動けるようにする、地味な足場への投資です。明らかな破損を捉える自動テスト群、儀式ではなく日常となったデプロイ、そして悪いリリースを慌てる代わりに数秒で止める手立てです。

  • 壊れたら破滅的になる、ひと握りのフローを覆うテスト群。ログイン、決済、中核となる操作。すべてではなく、重要な少数を。
  • 儀式ではなくボタンで走るデプロイ。小さく頻繁にリリースすることが、神経をすり減らすものではなく安全になるように。
  • 素早くロールバックする手段。悪いリリースが徹夜のインシデントではなく五分の出来事であるように。
  • フィーチャーフラグ。まず数人の顧客にコードを出し、おかしな挙動をしたら即座に切れるように。
  • 一人の休暇が製品の一領域まるごとを凍りつかせない程度のドキュメント。

このどれもデモには現れません。どれも直接には機能を足しません。そしてこれこそが、加速し続ける製品と、新規採用のたびに遅く挽かれていく製品とを分ける、まさにその作業です。うまくスケールするチームは、製品を安全に変更できる能力そのものを一つの機能として扱います。スケールにおいては、それがまさにそうだからです。

崩壊の局面からの短い物語

具体的にするために、私たちが手がけた仕事から組み立てた合成例を一つ。詳細はぼかし、形は実物に忠実です。フィールドサービスのチームを管理する小さなSaaSが、うまくローンチし、数百の有料企業まで成長しました。創業者たちは大喜びと疲弊を同じだけ抱えていました。そこへ、過去最大の顧客が契約しました。それまでの十社を合わせたよりも多くのユーザーと、多くの履歴データを持つ会社でした。

一週間のうちに、全員が住み着いていたダッシュボードが、その顧客にとって這うほど遅くなりました。そして奇妙なことに、他の全員にとっても遅くなったのです。サポートの問い合わせが急増しました。創業者たちは、はるかに大きなサーバーが必要だと思い込み、痛みを伴う高額な再設計に身構えていました。私たちが呼ばれたのはその瞬間であり、その直感は理解できるものでしたが、間違っていました。

私たちはアーキテクチャに手を触れませんでした。スロークエリログを有効にし、ひと午後ながめました。犯人はほとんど気恥ずかしいほど小さなものでした。メインのダッシュボードが、古典的なN+1パターンで各ユーザーのジョブ一覧を読み込み、ジョブごとに一つのクエリを発行していたのです。小さな顧客なら数十の無害なクエリでした。新しい巨大顧客では、ページ読み込みごとに数千を意味し、共有インフラ上でシステム全体を全員のために引きずり下ろしていました。

創業者たちが持ち帰った教訓は技術的なものではありませんでした。彼らが想像していた恐ろしいスケール問題、つまり作り直しと資金調達を要すると思っていたものが、計測してみれば、恐ろしい症状の裏に隠れた二日の修正だった、ということです。彼らは見当違いの問題の解決に何か月も費やそうとしていました。想像上の危機と計測された危機との、その隔たりこそ、スケールのための資金が最も無駄になる場所です。

本当に一部を作り直すべきとき

早すぎるスケールへのこうした慎重さは、決してリファクタリングするな、決して作り直すなと読めるかもしれません。そうではありません。ときに製品の一部は本当に寿命の終わりに達しており、もう一度パッチを当てるのが高くつく選択になります。コツは、本当の構造的限界と、計測された修正で片づく普通の成長痛とを見分けることです。

正直なサインはこうです。コンポーネントを作り直すのは、それを変更するコストが、置き換えるコストより一貫して高くなったときです。醜いから、ではありません。安定していてめったに触らない醜いコードは問題ありません。探しているのは、あらゆる変更が遅くリスキーで、同じバグが返り続け、新しい開発者が安全に作業できず、より安い修正をすでに試して壁に当たった、システムの一部です。そのいくつかが同時に当てはまるとき、その一部だけに絞った書き直しが正しい判断です。

サインおそらく修正で済むおそらく作り直し
症状一つの遅いページかクエリある領域のあらゆる変更が遅くリスキー
バグたまに起き、直せる同じバグが返り続ける
安い修正まだ試していないすでに尽き、なお行き詰まり
範囲一つの機能に収まるモジュール全体に広がる
正しい一手計測してパッチその一部だけを意図的に作り直す
計測された修正と、本物の作り直しとを見分ける。

そして作り直すときは、一部を作り直してください。製品をではなく。一からの全面書き直しはスケールのセイレーンの歌です。きれいに感じられ、結局は一年を沈め、その間に競合はリリースします。明確な境界の向こうで、腐った一つのコンポーネントを置き換え、残りの製品は動き続け稼ぎ続けます。英雄的にではなく、外科的に。

中の家族が日々の暮らしを続けるなか、職人がそれ以外は堅牢な家の、すり減った梁を一本だけ慎重に取り換えている、全面的な作り直しではなく狙いを定めたリファクタリングを伝える落ち着いたエディトリアル風イラスト
うまいスケールは、すり減った梁を一度に一本ずつ取り換えるように見えます。みんながまだ住んでいる家を取り壊すのではなく。

壁に当たって、修正か作り直しか分からない?

それは、間違えると高くつき、当てると安く済む判断です。あなたの製品が実際にどこで張り詰めているかを計測し、二日の修正なのか、もっと深いものなのかを正直にお伝えします。誰かが新しいコードを一行書く前に。

ソフトウェアのスケールへの取り組み方を見る

よくある質問

自分のSaaSがスケールの壁に当たりそうか、どう見分ければよいですか?
クラッシュではなく、スローモーションの症状に注意してください。ページが着実に遅くなる、同じバグが再発する、デプロイが今やリスキーに感じる、そしてサポートの問い合わせがユーザー数より速く増える、といったものです。これらはたいてい、どんな劇的な障害よりずっと前に現れます。早めに基本的なモニタリングを有効にすれば、壁にぶつかるのではなく、近づいてくるのが見えます。
スケールのためにマイクロサービスへ移るべきですか?
ほぼ確実にまだですし、おそらく永遠に不要です。マイクロサービスは、成長中のSaaS製品の多くが実際には抱えていない組織やスケールの問題を解決する一方で、日々の複雑さを大量に加えます。素早く変更できる、きれいでよく理解された一枚岩のほうが、触るのが怖い分散システムよりスケールします。そのアーキテクチャに手を伸ばすのは、具体的で計測された問題がそれを要求するときだけにしてください。
コードを最適化するのと、大きなサーバーを買うのと、どちらが安いですか?
ほぼ常に、まず最適化です。大きなサーバーは少しの余裕を買う毎月の継続コストですが、欠けたインデックスやN+1クエリを直すのは、たいてい一度きりの労力で、その後は無料、しかもしばしばはるかに大きな改善をもたらします。ハードウェアをスケールするのは、コードとクエリがすでにきれいになってからにしてください。
全面的な書き直しが本当に正しい判断なのは、どんなときですか?
まれであり、製品全体ではなく一度に一部だけです。コンポーネントを作り直すのは、その変更が置き換えより一貫して遅くリスキーになり、同じバグが返り続け、より安い修正をすでに使い尽くしたときです。それでも、その一つのコンポーネントを明確な境界の向こうで置き換え、残りは動かし続けます。一からの全面書き直しは、たいてい一年がかりの罠です。
ユーザーがいるより前に、スケールへどれくらい投資すべきですか?
意図的に、ごくわずかにです。素早く変更できる、きれいでシンプルなものを作り、問題が近づくのが見えるよう基本的なモニタリングを足し、それ以外は、到達していないスケールのためのインフラ構築を控えてください。スケールへの最良の備えは複雑なアーキテクチャではありません。シンプルな製品と、本当のボトルネックが現れたときにそれを安全に変えられるチームです。
Have a nice day
Have a nice day
編集部

Have a nice day は、中小企業のデジタル化を支援するソフトウェアスタジオです。スライド上だけでなく、日々の業務で本当に機能する自動化・AI・カスタムソフトウェアを提供します。

関連サービス