【アーキテクチャConference 2025】 スタートアップの事業成長を支えるアーキテクチャとエンジニアリング
2025年11月20日・11月21日に、ファインディ株式会社が主催するイベント「アーキテクチャConference 2025」が、ベルサール羽田空港にて開催されました。
20日に登壇した株式会社カナリー 開発本部 CTOを務める中山 太雅さんは、スタートアップの戦略を考える際は「立ち上げ期」と「拡大・運用期」という2フェーズに分けて考えるべきだと語ります。本セッションでは、技術的負債や品質問題と向き合いながら開発を続ける中で中山さんがたどり着いた、事業成長を阻害しないための「戦術」と「戦略」について、失敗事例なども交えながら語っていただきました。
■プロフィール
中山 太雅
株式会社カナリー
開発本部 CTO
慶應義塾大学卒業後、ソフトウェアベンダーに入社し受託開発と自社プロダクト開発を担当。その後、DeNAにてソーシャルゲームの企画・開発・運用に従事、主にバックエンドやUnityを利用した3Dアプリ開発を経験。大手金融グループでブロックチェーンのリサーチなどを経てシード期のスタートアップにジョイン、Web フロントエンドの立ち上げを行う。その後、株式会社カナリーに入社。
負債を「返済する」よりも「生まない」ための武器
皆さんこんにちは、カナリーの中山です。本日は、エンジニアやテックリード見習いの方に向けて、私の経験則に基づいた「スタートアップの事業成長を支えるアーキテクチャとエンジニアリング」についてお話しします。
現在、弊社では不動産DX事業とDXソリューション事業を展開していますが、本日は前者の事例を踏まえてお話します。不動産DX事業では複数のプロダクトを提供しており、それぞれにフェーズが異なります。具体的には、0→1の新規プロダクトに加えて、1→10の拡大フェーズにある顧客管理システム「CANARY Cloud CRM」、10→100フェーズの不動産マーケットプレイス「CANARY」といったサービスがあります。
これはCTOである私の責任でもありますが、異なるフェーズのサービスを並行開発していると「この失敗、どこかで見たことあるな」という問題が発生しがちです。本日は、このような問題を回避できるように「負債を生まないための武器」についてお話しします。
開発現場で起きるバグ、パフォーマンス低下、運用負荷の増大といった問題は、「品質の連鎖」として捉えることができます。ユーザーが体験する「利用時の品質」の裏には、正しく動くという「外部品質」があり、さらにその内側にはコードや構造といった「内部品質」が存在します。この内部品質の裏側にあるのが、開発組織や個人のスキルといった「プロセスの品質」です。つまり、戦術(知識・スキル)や戦略(投資の意思決定)の欠如が、最終的なプロダクトの問題として表出しているのです。
ここで我々の状況を改めて整理すると、カナリーはスタートアップであり、リソースが限られているため、最初から完璧を目指すのは現実的ではありません。加えて、システムには「慣性」があり、一度悪い方に進むと、その方向に進み続けてしまいます。また、Webサービスは開発して終わりではなく、常に運用し続ける必要があります。
このような状況を打破するため、私は「立ち上げ期」と「拡大・運用期」という2つのフェーズに分けて考えることにしました。

立ち上げ期の「守」:システムの品質を支えるアーキテクチャとインテグリティ
立ち上げ期は、守破離の「守」で戦術のツボを押さえることが重要です。「守」は基本の型を忠実に守ること、「破」は「守」を徹底した上で独自の考えを組み合わせて進化させること、「離」はそれらが熟達の域に達し、自ら新しい道を歩むこと。守破離とは、こういった進化の過程を意味しています。
よく言われる話ですが「型無し」と「型破り」は異なります。型破りは守るべき基本を理解した上で破っていくのに対し、型無しは基本を理解せずに「破」や「離」に挑戦することを意味します。これでは上手くいきません。「守」を全うし、トレードオフを理解した上で「破」や「離」に挑戦することが大切だと思います。
ここからは、立ち上げ期の「守」としてピックアップした6つについてご紹介します。

~アーキテクチャの守~
「アーキテクチャの守」は「理由なくマイクロサービスにしない」です。「何事にもトレードオフがある」と言われるように、マイクロサービスで何を得て何を失うのかを見極める必要があります。マイクロサービスには「トランザクション境界の出現」や「レイテンシーの悪化」「コードやCI/CD、オブザーバビリティの複雑化」など、デメリットもたくさんあります。
「大変なのに、なぜマイクロサービスにするのか?」という問いに、皆さんはどのように答えますか? この時、メリットがデメリットを上回ると即答できないのであればマイクロサービスを導入すべきではない、というのが私の考えです。流行り言葉に流されず、トレードオフをしっかり見極めることが大切です。
~インテグリティの守~
次に、データ整合性を保つための「インテグリティの守」については、3つの守があります。
1つ目は「更新時は排他制御(競合制御)を行う」です。例えば、在庫が10の状態で、AさんとBさんが同時に1減らす操作をした場合、排他制御がなければ二人とも10を読み取って9に書き換えてしまい、在庫が1しか減らない整合性の不一致が起きます。他者が操作をしている時は読み込み時点でロックをかけるなど、順序正しく処理されるようにする必要があります。

2つ目は「整合性チェックは信頼できるデータで行う」です。負担分散のためにレプリカからデータを読んで整合性チェックを行うと、最新の状態を無視してしまうため、データが壊れる可能性があります。更新に関わるチェックは、必ず信頼できるプライマリーの値をロックした状態で行うべきです。

3つ目は「トランザクションは基本的に1つにする」です。下記の画像に載せているような擬似コードはあまりないと思いますが、ここに書かれているのは、出金と入金の処理です。出金でトランザクションを閉じてから入金処理を行う設計では、処理間でシステムが落ちた場合に「出金されたが入金されていない」という最悪の状態を招きます。アトミシティ(原子性)を担保するため、一連の処理は1つのトランザクションで完結させるのが基本です。


これらは当たり前のことに思えますが、実際には守られていないケースもあるのです。私が過去にソーシャルゲームを開発していた際、1体のレイドボスへ同時攻撃する時にデータベースのコネクションをハッシュのキーで取り出していたため順序が不定となり、本当にわずかなコミット順の違いでデータが壊れるという経験をしました。0.1%の確率でしか起きないようなバグも、10万リクエストがあれば100回発生します。雪だるま式に問題が大きくなる前に、設計段階で防いでおくことが非常に重要です。
立ち上げ期の「守」:メンテナンス性とユーザビリティへの配慮
~メンテナビリティの守~
「メンテナビリティの守」についても触れたいと思います。1つ目は「コメントをちゃんと書く」です。ここで言うコメントとは、処理内容そのものではなく、「概念」や「背景・理由」の説明です。例えば、「PKモデル」というクラスがあったとして、単にそう書いてあるだけでは理解できませんが「薬が体内でどう減っていくかを数値的に扱うモデル」と説明があれば、概念が伝わります。

また、処理に対して「指数的なペナルティを設定」と書くのではなく、「低回転時のノッキングを避けたい、高回転時の騒音を抑制したいから、強く禁止するためにペナルティを重くしている」といった背景(Why)が書かれていれば、後からコードを触る人も安心して修正できます。コードには、読み手に対する「ホスピタリティ」が必要なのです。

2つ目は「設計原則を守る」です。巨大なものは扱いづらいため、分割して可読性・再利用性・テスト可能性を向上します。また、カプセル化によって、データと振る舞いをまとめて外部からの不正な書き換えを防ぐのも大切です。最後に、疎結合・高凝集の維持も重要です。例えば、メール送信ロジックが特定のキャンペーンのことを知っていると、メールを修正する際にキャンペーンの詳細知識が必要となり、相互依存が発生します。そういったことを防ぐためには、上位や横の概念を知らなくていいように設計し、1つのことに集中させることが大事です。

これらの話は、DDDにおけるコンテキストや集約、レイヤーといった概念にも通じる奥義です。責務を小さく扱いやすくした上で、カプセル化、疎結合・高凝集を目指して組み立てていくと、持続可能なシステムが構築できると。詳細については、下記に挙げているような素晴らしい書籍を読まれることを推奨します。

~ユーザビリティの守~
続けてお話しする「ユーザビリティの守」は「準正常系のエラーを返せる道を作る」です。処理結果を3つに分類すると、正常に処理を終了できる「正常系」、ドメイン上想定内のエラーである「準正常系」、回復不能な「異常系」に分けられます。準正常系を適切にハンドリングしてフロントエンドに返さないと、ユーザーは原因不明のエラーに直面し、次のアクションが取れなくなります。具体的な原因を通知するように設計するのが、テックリードやアーキテクトの大事な役割です。

~オブザーバビリティの守~
次の「オブザーバビリティの守」は「ログを過不足なく出せるようにする」です。オブザーバリティの三本柱には「ログ(何が起きたかピンポイント)/メトリクス(定量的情報)/トレース(全体像)」があります。最近は四本柱とも言われていますが、ここでは三本柱とします。
これらは全て重要ですが、小規模なうちは「ログ」を大事にしましょう。エラーで動かないものはどうやっても動きませんし、それに気付けないのは大きな問題です。
ログのツボとしては「過不足なく捕捉できることが重要」です。ロガーを整備して、出したい時に出せる状態にしておく。ログレベルをちゃんと切り分けて、JSONなどで構造化しましょう。Go言語の場合、スタックトレースが出ずにエラーメッセージだけが出ると、場所の特定に時間がかかります。フロントエンドも例外を捕捉できるように整備しましょう。

~スケーラビリティの守~
「スケーラビリティの守」の1つ目は「データベースにインデックスを張る」です。インデックスがないとしらみつぶしにレコードを探していくことになるため、時間がかかります。インデックスがあると、だいたいの位置が分かるため、時間を短縮できます。実装によって異なるため、下図は正確なものではありませんが、イメージとして例を載せています。

2つ目は「データベースのN+1問題に気を付ける」です。例えば、記事の一覧を取得したあと、記事ごとに作者の情報を1件ずつ取得すると、大量のクエリが発行されてしまいます。そうするよりも、必要な作者のIDをまとめて指定して1回のクエリで一括取得する方が効率的です。

立ち上げ期の守は以上です。私の経験上、よく軽視されがちだけれども、やっておくと“いい感じのシステム”になる、というツボをお伝えしました。

拡大・運用期は投資ゲーム?見落とされがちな二大巨頭とは
次に、拡大・運用期についてお話しします。この時期に入ると、戦い方は「投資ゲーム」へと変化します。エンジニアリングリソースは有限であり、どこに投資するかで未来が決まります。運用は長期にわたるマラソンであり、短期のアウトプットに集中すると、茹でガエル式に状態が悪化してしまう。だからこそ、見過ごされがちな投資先を知っておくことが重要です。
拡大・運用期に見落とされがちな投資先の二大巨頭は「運用負荷」と「内部品質」です。「運用負荷」について、マスタデータの更新や設定変更などの運用作業が増えると、エンジニアが疲弊して退職に繋がりやすくなる。スタートアップでは「今問題がないなら後回し」と考えがちですが、短期目線で新規開発を続けると、いつの間にか運用負荷が高まってしまいます。
これを防ぐための対応策として、手順書やQ&A集を制作するだけでも、負荷を軽減できます。工数を割けるのであれば、スクリプトを作って自動化するのもおすすめです。内部管理画面やSlackコマンドを作ると、かなり楽になるのではないでしょうか。実際に、弊社はこういったことを通して、運用負荷を下げられていると実感できています。
次は「内部品質」についてお話しします。いわゆる技術的負債への対応ですね。下図はマーチン・ファウラー氏が提唱した「技術的負債の四象限」から出典しています。

認知外/無謀の枠については、問題を認知できていない状態であるため、スキルを向上して認知できる負債の種類を増やす必要があります。スキルを向上して認知できる負債を増やすと、意図的/無謀の枠に移動します。
ただ、意図的/無謀な状態が続くと、利息(速度の低下)を払えなくなるため、コントロール下に置きたいと。コントロールについては後でお話しします。次に、認知外/慎重については避けようがないため、最善を尽くして起きてしまったなら対処するしかないと思います。
意図的/慎重については、計画的に対処することを決めているパターンだと思います。ただ、ここは場合によって変わるため「コントロール下に置く」というお話しだと思っています。
「コントロール下に置く」とはなんなのか?簡単に言うと、1つ目は「利息が発生するのかどうか」です。その後修正しないのであれば利息は発生しませんし、意図的に対処しない判断もできるでしょう。
2つ目が「分割返済」です。負債の上に負債を積み上げると、複雑性が増してしまいます。また、一括返済は複雑性・不確実性が高いため避けたい。それならば分割しながら返済しよう、というものです。
ここで重要な経験則についてお話しさせてください。下図でオレンジで色付けされているのは、弊社のとあるシステム上、ビジネス的に重要なドメインを指しています。加えて右下に赤い三角が出ている部分は、強くいじりづらいという意見が出ている部分です。赤い三角が出ている部分は、CodeSceneのスコアも良くありません。この図を見てわかる通り、ビジネス的に重要なドメインは、いじりづらいという意見が良く出ています。

何が言いたいかというと、ビジネス的に重要な場所は良く変更(拡張)するため、変化に合わせて適切な形にしないと、負債化しやすくなってしまうということ。重要な場所が負債化するのは、ビジネス的には最悪のパターンでしょう。だからこそ、重要な場所ほど整頓されている価値が高いと言えますし、そういった意識を持つことが大事なのではないかと考えています。
一括返済についてもお話しします。負債を蓄積していくと、最終的には「本当に直せるのか?」という状態になってしまいます。そうなると不確実性が高く、事業計画上の扱いも難しくなってしまいます。例えば、技術負債の返済に半年ほどかかるとなると「そんなに時間をかける意味はあるのか?」という疑問が出てくるため、負債を返済するメリットを定量的に示す必要があります。
しかし、マーチン・ファウラー氏も言っている通り、負債について定量化するのは基本的に難しいんですよね。そういった事態を避けるためにも、リスクと工数を小さく分割して、コントロールできるうちに返済する。必要経費と割り切って、分割返済することが大切なのだと思います。
つまり「コントロール下に置く」とは、スキルを学んで認識できる負債の種類を増やし、利息が発生するかどうかを考え、重要な場所ほど整頓に投資することを意味しています。利息が発生する負債は返済までがセットであり、一括返済のリスクを避けて分割返済する、という意識を持つことが重要です。
負債化させない武器(知識)を手に、成長を続けていく

まとめます。立ち上げ期は守破離の「守」を意識し、基本に忠実に、ツボを押さえた戦術で戦うことが大切です。
拡大・運用期はエンジニアリングは「投資ゲーム」であると意識して「運用負荷」と「内部品質」に投資することが求められます。茹でガエルに注意して、運用負荷を計測・対処しましょう。また、重要なところほど整頓し続け、負債化させないことが大事だと思います。
ここまでお話しした以外にも、拡大・運用期にシステム的に考えるべきことはたくさんあります。しかし、時間の都合もあるため、本日はここまでとさせていただきます。
ご清聴ありがとうございました。

アーカイブ動画・発表資料
イベント本編は、アーカイブ動画を公開しています。また、当日の発表資料も掲載しています。あわせてご覧ください。
▼動画・資料はこちら
アーキテクチャConference 2025
※動画の視聴にはFindyへのログインが必要です。






