Slide 1

Slide 1 text

2025.11.20 スタートアップの事業成⻑を⽀える アーキテクチャとエンジニアリング アーキテクチャ Conference 2025 株式会社カナリー CTO 中⼭ 太雅

Slide 2

Slide 2 text

経験則に基づく要点のみお伝えします 全体観には⽋ける部分もあります ⚠ 注意 エンジニア テックリード⾒習い プロダクトマネージャ プロダクトオーナー 想定ターゲット

Slide 3

Slide 3 text

写真を ⼊れてください 略歴 ⾃⼰紹介 2006年 2011年 2018年 2023年 中⼭ 太雅 開発本部 CTO 慶應義塾⼤学 環境情報学部卒 🚗 レーシングドライバーを⽬指す(?) 株式会社ディー‧エヌ‧エー ⾼トラフィックのソーシャルゲームの新規開発‧運⽤ ⾦融系、個⼈事業主、スタートアップ等を経験 株式会社カナリー CTO | 事業を技術で⽀え‧ドライブする

Slide 4

Slide 4 text

Startup CTO of the Year 2025 ファイナリスト

Slide 5

Slide 5 text

株式会社カナリーの事業 不動産DX事業 不動産マーケットプレイス 不動産業界向けSaaS DXソリューションズ事業 企業のDX推進 コンサルティング

Slide 6

Slide 6 text

サービスの規模 0-1 1-10 10-100 新規プロダクトA 新規プロダクトB 多様なフェーズのサービスが存在 新規プロダクトA 新規プロダクトB CANARY Cloud CRM マーケットプレイス

Slide 7

Slide 7 text

この失敗 どこかで⾒たことがあるな…

Slide 8

Slide 8 text

機能追加‧変更時に⾼頻度でバグが発⽣ エンジニアが問題の発⽣に気付けない ⼀部の顧客でパフォーマンスが悪化 原因不明の⼀貫性のないデータ 運⽤負荷が⾼すぎて仕事にならない

Slide 9

Slide 9 text

※瀧本哲史さんのオマージュ 私は皆さんに武器を配りたい

Slide 10

Slide 10 text

何故問題が起きてしまうのか?

Slide 11

Slide 11 text

※ISO25010 等を元に平易な⾔葉に置き換えています ? ? 内部品質 外部品質 利⽤時の品質 分かりやすさ 修正しやすさ テストしやすさ etc 性能 信頼性 使いやすさ etc 価値 コスト 気持ちよさ etc

Slide 12

Slide 12 text

※ISO25010 等を元に平易な⾔葉に置き換えています プロセス‧資源品質 内部品質 外部品質 利⽤時の品質 開発組織 開発⼿法 知識‧スキル 分かりやすさ 修正しやすさ テストしやすさ etc 性能 信頼性 使いやすさ etc 価値 コスト 気持ちよさ etc

Slide 13

Slide 13 text

プロセス‧資源品質 戦術‧戦略の⽋如 ※ISO25010 等を元に平易な⾔葉に置き換えています 内部品質 外部品質 利⽤時の品質 開発組織 開発⼿法 知識‧スキル 分かりやすさ 修正しやすさ テストしやすさ etc 性能 信頼性 使いやすさ etc 価値 コスト 気持ちよさ etc

Slide 14

Slide 14 text

品質を⾼く保つための知識‧スキル 戦術 戦⼒‧戦術を投⼊する投資の意思 戦略

Slide 15

Slide 15 text

状況認識

Slide 16

Slide 16 text

状況認識 悪い⽅向を向くとその⽅向に進み続ける 雪だるま式に悪い品質が積み上がる システムの慣性 リソースが限られている 最初から全⽅位で完璧にすることは難しい スタートアップ 開発して終わりではない 作り‧変え‧拡張‧連携‧運⽤し続ける Web サービス

Slide 17

Slide 17 text

どうすればよいのか?

Slide 18

Slide 18 text

守破離の「守」で戦術のツボを抑える 時期尚早な最適化はしない ⽴上期 必要に応じて「破」や「離」を考える 「投資ゲーム」であることを意識 拡⼤ 運⽤期

Slide 19

Slide 19 text

⽴上期

Slide 20

Slide 20 text

守破離の「守」で 戦術のツボを抑える

Slide 21

Slide 21 text

「守破離」とは 守 破 離 熟達の域に達し、 型に囚われず ⾃ら新しい道を歩む 新しい考え⽅や 独⾃の考えを組み合わせ 型を破り進化させる 基本の型を忠実に守る

Slide 22

Slide 22 text

「守破離」とは 守 破 離 熟達の域に達し、 型に囚われず ⾃ら新しい道を歩む 新しい考え⽅や 独⾃の考えを組み合わせ 型を破り進化させる 基本の型を忠実に守る 型なし ≠ 型破り トレードオフを理解してからの破や離

Slide 23

Slide 23 text

⽴上期の「守」 1. アーキテクチャ 2. インテグリティ 3. メンテナビリティ 4. ユーザビリティ 5. オブザーバビリティ 6. スケーラビリティ

Slide 24

Slide 24 text

アーキテクチャの守 〜トレードオフを⾒極める〜

Slide 25

Slide 25 text

理由なくマイクロサービスにしない ⼀ノ守

Slide 26

Slide 26 text

アーキテクチャの守 〜トレードオフを⾒極める〜 何事にもトレードオフ があるのじゃ 偉い⼈

Slide 27

Slide 27 text

アーキテクチャの守 〜トレードオフを⾒極める〜 何事にもトレードオフ があるのじゃ 偉い⼈ マイクロサービスで何を得て 何を失っているのか?

Slide 28

Slide 28 text

アーキテクチャの守 〜トレードオフを⾒極める〜 デメリット トランザクション境界の出現 レイテンシーの悪化 コードの複雑化 CI / CD の複雑化 オブザーバビリティの複雑化

Slide 29

Slide 29 text

アーキテクチャの守 〜トレードオフを⾒極める〜 デメリット メリット トランザクション境界の出現 レイテンシーの悪化 コードの複雑化 CI / CD の複雑化 オブザーバビリティの複雑化 ?

Slide 30

Slide 30 text

アーキテクチャの守 〜トレードオフを⾒極める〜 そんなに⼤変なのに何故あなたは マイクロサービスにするのですか?

Slide 31

Slide 31 text

アーキテクチャの守 〜トレードオフを⾒極める〜 そんなに⼤変なのに何故あなたは マイクロサービスにするのですか? 答えられないなら必要ない 状況的に worth だと考えるなら導⼊

Slide 32

Slide 32 text

インテグリティの守 〜データが壊れないようにする〜

Slide 33

Slide 33 text

更新時は排他制御(競合制御)を⾏う ⼀ノ守 ⼆ノ守 三ノ守

Slide 34

Slide 34 text

インテグリティの守 〜データが壊れないようにする〜 ⼀ノ守 排他制御なし 在庫が1つ増えた…?!

Slide 35

Slide 35 text

インテグリティの守 〜データが壊れないようにする〜 ⼀ノ守 排他制御なし 排他制御あり 在庫が1つ増えた…?! ※データベースの種類によってはこの図が正確でない場合もあります

Slide 36

Slide 36 text

整合性チェックは信頼できるデータで⾏う 更新時は排他制御(競合制御)を⾏う ⼀ノ守 ⼆ノ守 三ノ守

Slide 37

Slide 37 text

インテグリティの守 〜データが壊れないようにする〜 ⼆ノ守 信頼できないデータで検証 最新の状態を無視してしまう ※楽観ロックをしている場合は問題ないこともあります

Slide 38

Slide 38 text

インテグリティの守 〜データが壊れないようにする〜 ⼆ノ守 信頼できないデータで検証 信頼できるデータで検証 最新の状態を無視してしまう ※楽観ロックをしている場合は問題ないこともあります

Slide 39

Slide 39 text

更新時は排他制御(競合制御)を⾏う ⼀ノ守 トランザクションは基本的に1つ 三ノ守 整合性チェックは信頼できるデータで⾏う ⼆ノ守

Slide 40

Slide 40 text

インテグリティの守 〜データが壊れないようにする〜 三ノ守 TX が細切れ ※あくまで概念の説明で実際にはマイナスにならないようにコードで制御したりもっと複雑になります 途中で失敗すると 整合性が保てない

Slide 41

Slide 41 text

インテグリティの守 〜データが壊れないようにする〜 三ノ守 TX は1つ ※あくまで概念の説明で実際にはマイナスにならないようにコードで制御したりもっと複雑になります 全体が成功するか 全体が失敗するか

Slide 42

Slide 42 text

インテグリティの守 〜データが壊れないようにする〜 「そんなこと気にしても問題なんか起きないんじゃない?」 トラフィックが増えると問題が起きる 100,000リクエスト * 0.1% = 100回 (調査‧対応‧報告‧振り返り)の時間‧信頼の毀損 雪だるまになってから直すのは⼤変

Slide 43

Slide 43 text

メンテナビリティの守 〜変更に強いコードベースにする〜

Slide 44

Slide 44 text

コメントを書く ⼀ノ守 ⼆ノ守

Slide 45

Slide 45 text

メンテナビリティの守 ⼀ノ守 何故コメントが重要なのか? コードをメンテナンスするには先ず理解する必要がある コードには現れていない知識や背景がある コードをメンテナンスするのは「あなただけではない」

Slide 46

Slide 46 text

メンテナビリティの守 ⼀ノ守 何故コメントが重要なのか? コードをメンテナンスするには先ず理解する必要がある コードには現れていない知識や背景がある コードをメンテナンスするのは「あなただけではない」 おもてなしの⼼で「優しく教えてあげる」 ホスピタリティ

Slide 47

Slide 47 text

メンテナビリティの守 ⼀ノ守 1. 「概念」を説明する ○ 分からない⼈は「なにもわからない」 ○ ⼤枠の概念の仮定(メンタルモデル)を作ってあげる ○ フィールドだけでなく「概念⾃体」にコメントを書く 2. 背景‧理由を説明する ○ 何故そうしたのか、コードから読み取れない背景を書く ○ 読めば分かる処理の内容⾃体を書いても意味がない

Slide 48

Slide 48 text

メンテナビリティの守 ⼀ノ守 概念にコメントがない え、なに…これ…?

Slide 49

Slide 49 text

メンテナビリティの守 ⼀ノ守 概念にコメントがない 概念にコメントがある え、なに…これ…? 薬効のモデルなのか! ※ChatGPT に⽣成させたイメージです

Slide 50

Slide 50 text

メンテナビリティの守 ⼀ノ守 処理の内容そのまま それは⾒れば分かるけど…

Slide 51

Slide 51 text

メンテナビリティの守 ⼀ノ守 処理の内容そのまま 背景‧理由を指すコメント それは⾒れば分かるけど… そういうことなんですね〜 ※ChatGPT に⽣成させたイメージです

Slide 52

Slide 52 text

コメントを書く ⼀ノ守 設計原則を守る ⼆ノ守

Slide 53

Slide 53 text

メンテナビリティの守 ⼆ノ守 ⼤きいものは扱いづらい 分割して可読性‧再利⽤性‧テスト可能性を上げる 分割統治 知らなくていいことは知らない ひとつのことに集中する 疎結合 ⾼凝集 データと振る舞いをひとまとまりとしてモデリング 内部を隠蔽化し振る舞いに対する責任を取らせる カプセル化

Slide 54

Slide 54 text

メンテナビリティの守 ⼆ノ守 メンテナビリティに関して 私は真に驚くべきツボを⾒つけたが それを40分で議論するには短すぎる

Slide 55

Slide 55 text

メンテナビリティの守 ⼆ノ守 冗談です😆 基本にして奥義 私には畏れ多い領域 以下の⽅々の本などを読まれることを推奨 ● 増⽥ 亨 ● 和⽥ 卓⼈ ● Robert C. Martin ● Martin Fowler ● Kent Beck ● Vlad Khononov

Slide 56

Slide 56 text

ユーザビリティの守 〜UX に優しいアーキテクチャ〜

Slide 57

Slide 57 text

準正常系のエラーを返せる道を作る ⼀ノ守

Slide 58

Slide 58 text

ユーザビリティの守 〜UX に優しいアーキテクチャ〜 ⼀ノ守 正常に処理を終了できた 正常系 処理は期待通り終了できなかった、想定できず回復不能 異常系 処理は期待通り終了できなかったが想定の範囲内のエラー 準正常系

Slide 59

Slide 59 text

ユーザビリティの守 〜UX に優しいアーキテクチャ〜 ⼀ノ守 準正常系を返せない どうしろって⾔うの…?

Slide 60

Slide 60 text

ユーザビリティの守 〜UX に優しいアーキテクチャ〜 ⼀ノ守 準正常系を返せない 準正常系を返せる どうしろって⾔うの…? 原因が分かるので対処できる

Slide 61

Slide 61 text

ユーザビリティの守 〜UX に優しいアーキテクチャ〜 ⼀ノ守 {"error":{"code":"validation_failed"...}} REST union FooResult = FooSuccess | FooError GraphQL ErrorDetails を利⽤ gRPC

Slide 62

Slide 62 text

オブザーバビリティの守 〜起きていることを知る〜

Slide 63

Slide 63 text

ログを過不⾜なく出せるようにする ⼀ノ守

Slide 64

Slide 64 text

オブザーバビリティの守 〜起きていることを知る〜 ⼀の守 ログ メトリクス トレース 何が起きたか ピンポイント どれくらい 定量的情報 全体像

Slide 65

Slide 65 text

オブザーバビリティの守 〜起きていることを知る〜 ⼀の守 ログ メトリクス トレース 何が起きたか ピンポイント どれくらい 定量的情報 全体像 全部⼤事だが “あえて” ⼩規模システムで究極の選択をするなら ログ > メトリクス > トレース ● エラーで動かないものはどうやっても動かないのでクリティカル ● 外部システムを多⽤していなければトレースよりもメトリクスの⽅が嬉しい

Slide 66

Slide 66 text

オブザーバビリティの守 〜起きていることを知る〜 ⼀の守 ● まずはログが過不⾜なく捕捉できることが重要 ○ ロガーが整備されていてログを出したい時に出せること ○ ログレベルの切り分けができていること(本当にエラーになるべきものの切り分け) ○ 構造化されていること(JSON など‧分析時に楽) ○ スタックトレースが⾒れること(Go の場合) ○ フロントエンドの場合は Unhandled な例外も捕捉できるように

Slide 67

Slide 67 text

スケーラビリティの守 〜ユーザー増加に備える〜

Slide 68

Slide 68 text

データベースにインデックスを張る ⼀ノ守 ⼆ノ守

Slide 69

Slide 69 text

スケーラビリティの守 ⼀ノ守 インデックスがない しらみ潰しに探すので遅い

Slide 70

Slide 70 text

スケーラビリティの守 ⼀ノ守 インデックスがない インデックスがある しらみ潰しに探すので遅い だいたいの位置が分かるので速い ※多様な実装があるので必ずしも正確な図ではありません

Slide 71

Slide 71 text

データベースにインデックスを張る ⼀ノ守 データベースの N+1 問題に気を付ける ⼆ノ守

Slide 72

Slide 72 text

スケーラビリティの守 ⼆ノ守 レコードを1つずつ取ってしまう 記事毎のクエリが発⾏され遅い

Slide 73

Slide 73 text

スケーラビリティの守 ⼆ノ守 レコードを1つずつ取ってしまう 取れるレコードは⼀気に取る 記事毎のクエリが発⾏され遅い ⼀括で取得するので速い

Slide 74

Slide 74 text

⽴ち上げ期の守 戦術のツボを抑えた! ✅ 理由なくマイクロサービスにしない ✅ 更新時は排他制御(競合制御)を⾏う ✅ 整合性チェックは信頼できるデータで⾏う ✅ トランザクションは基本的に1つ ✅ コメントを書く ✅ 設計原則を守る ✅ 準正常系のエラーを返せる道を作る ✅ ログを過不⾜なく出せるようにする ✅ データベースにインデックスを張る ✅ データベースの N+1 問題に気を付ける

Slide 75

Slide 75 text

拡⼤‧運⽤期

Slide 76

Slide 76 text

投資ゲーム

Slide 77

Slide 77 text

拡⼤‧運⽤期 エンジニアリングリソース 投資先 社員 業務委託 AI MTG 設計 コーディング 教育 採⽤ …? 有限な時間の投資先で未来を決めている

Slide 78

Slide 78 text

拡⼤‧運⽤期 運⽤は⻑期に渡るマラソン 短期のアウトプットに集中すると 茹でガエル式に状態が悪化する

Slide 79

Slide 79 text

拡⼤‧運⽤期 運⽤は⻑期に渡るマラソン 短期のアウトプットに集中すると 茹でガエル式に状態が悪化する ⾒過ごされがちな時間の投資先を知る

Slide 80

Slide 80 text

運⽤負荷 内部品質 ⾒過ごされがちな投資先の⼆⼤巨頭

Slide 81

Slide 81 text

運⽤負荷

Slide 82

Slide 82 text

運⽤負荷 マスターの更新‧設定の変更など 運⽤の作業が多すぎて開発に時間が使えない 単調作業や調査でエンジニアが疲労 出⼒の低下‧エンジニアの離職

Slide 83

Slide 83 text

運⽤負荷 原因 ● スタートアップは「問題がない なら考えない」という思考にな りがち(ある種正しい) ● 結果、短期⽬線で新規開発だけ をやり続ける ● 気付くといつの間にか茹でガエ ル式に運⽤負荷が⾼まる 短期のアウトプットに偏重

Slide 84

Slide 84 text

運⽤負荷 原因 対応 ● スタートアップは「問題がない なら考えない」という思考にな りがち(ある種正しい) ● 結果、短期⽬線で新規開発だけ をやり続ける ● 気付くといつの間にか茹でガエ ル式に運⽤負荷が⾼まる 短期のアウトプットに偏重 ● PdM、PO と会話し投資先の⼀ つであるという共通認識を持つ ● 運⽤を楽にすれば時間を使える ようになるのでエンジニアも PdM‧PO も嬉しい ● どの程度リソースを使っている のか定量的に状況把握 共通認識の醸成‧状況把握

Slide 85

Slide 85 text

運⽤負荷 対応に要している作業の種類‧時間を計測 頻度‧削減時間‧改善⼯数からコスパがよさそうなものを⾒極める 1. ⼿順書‧Q&A集を作る 2. スクリプトを作る 3. 内部管理画⾯‧Slack コマンド等を作る

Slide 86

Slide 86 text

内部品質

Slide 87

Slide 87 text

…と⾔えば技術的負債

Slide 88

Slide 88 text

技術的負債の四象限(出典:マーチン‧ファウラー) 意図的 / 無謀 「時間ないんだよね」 意図的 / 慎重 「⼤丈夫、分かってる」 認知外 / 無謀 「レイヤー化ってなに?」 認知外 / 慎重 「もっとうまくできたな」 無謀 慎重 意図的 認知外

Slide 89

Slide 89 text

技術的負債の四象限(出典:マーチン‧ファウラー) 意図的 / 無謀 「時間ないんだよね」 意図的 / 慎重 「⼤丈夫、分かってる」 スキルの向上 認知できる負債を増やす 認知外 / 慎重 「もっとうまくできたな」 無謀 慎重 意図的 認知外

Slide 90

Slide 90 text

技術的負債の四象限(出典:マーチン‧ファウラー) 利息を払えなくなるので コントロール下に置く 意図的 / 慎重 「⼤丈夫、分かってる」 スキルの向上 認知できる負債を増やす 認知外 / 慎重 「もっとうまくできたな」 無謀 慎重 意図的 認知外

Slide 91

Slide 91 text

技術的負債の四象限(出典:マーチン‧ファウラー) 利息を払えなくなるので コントロール下に置く 意図的 / 慎重 「⼤丈夫、分かってる」 スキルの向上 認知できる負債を増やす 避けようがない 最善を尽くし起きたら対処 無謀 慎重 意図的 認知外

Slide 92

Slide 92 text

技術的負債の四象限(出典:マーチン‧ファウラー) 利息を払えなくなるので コントロール下に置く 場合によるので コントロール下に置く スキルの向上 認知できる負債を増やす 避けようがない 最善を尽くし起きたら対処 無謀 慎重 意図的 認知外

Slide 93

Slide 93 text

技術的負債の四象限(出典:マーチン‧ファウラー) 利息を払えなくなるので コントロール下に置く 場合によるので コントロール下に置く スキルの向上 認知できる負債を増やす 避けようがない 最善を尽くし起きたら対処 無謀 慎重 意図的 認知外 コントロール下?🤔

Slide 94

Slide 94 text

利息(速度の低下)が発⽣するかどうか 変更しない場所であれば利息は発⽣しない 利息 負債の上に負債を積み上げると複雑性が増す ⼀括返済は複雑性‧不確実性が⾼い 分割返済

Slide 95

Slide 95 text

技術的負債 ● ビジネス的に重要な場所はよく変更する ● よく変更するので負債化しやすい ● 重要な場所が負債化するのはビジネス的 には最悪パターン 重要な経験則 ※「いじりにくい」という意⾒が出ているものは CodeScene のスコアも悪い

Slide 96

Slide 96 text

技術的負債 ● ビジネス的に重要な場所はよく変更する ● よく変更するので負債化しやすい ● 重要な場所が負債化するのはビジネス的 には最悪パターン 重要な経験則 重要な場所ほど よく変更するので 整頓されている価値が⾼い ※「いじりにくい」という意⾒が出ているものは CodeScene のスコアも悪い

Slide 97

Slide 97 text

技術的負債 ⼀括返済 不確実性が⾼くリスク⾼ 事業計画上も扱いが難しい 全体リプレースの議論も発⽣ 返済!!

Slide 98

Slide 98 text

技術的負債 ⼀括返済 分割返済 リスクと⼯数を⼩さく分割 コントロールできるうちに返済 必要経費と割り切る 不確実性が⾼くリスク⾼ 事業計画上も扱いが難しい 全体リプレースの議論も発⽣ 返済!!

Slide 99

Slide 99 text

技術的負債 コントロール下に置く ● スキルを学び 認識できる負債の種類を増やす ● 利息が発⽣するかどうかを考える ● 重要な場所ほど 整頓し続ける投資を⾏う ● 利息が発⽣する負債は返済までがセット ● ⼀括返済はリスクが⾼いので 分割で返済

Slide 100

Slide 100 text

まとめ ● ⽴ち上げ期は守破離の「守」を意識 ○ 基本に忠実にツボを抑えた戦術で戦う ● 拡⼤‧運⽤は「投資ゲーム」であることを意識 ○ 「運⽤負荷」と「内部品質」も投資先 ○ 茹でガエルに注意し運⽤負荷を計測‧対処 ○ 重要なところほど整頓し続け負債化させない