システム設計 · ソフトウェアエンジニアリング

大企業のソフトウェア開発:
コードを書く前に考え抜くべきこと

「なぜ作るのか」からデザインレビューまで。システム設計で問うべきことと、その問いが防ごうとしているリスクを、ひとつの実例を通して最初から最後まで解説します。

目次
  1. 第1章:設計を始める前に
    1. なぜこの機能を作るのか
    2. どう実装するのか
    3. ユーザー規模とデータ量
    4. システムの制約
    5. ユーザーあたりのコスト
    6. 人員と期間
    7. 既存システムとの互換性
  2. 第2章:設計するとき
    1. 経営者の視点で判断する
    2. PoC とプロトタイプ
  3. 第3章:デザインレビューで
    1. Q1 課題・機能・規模
    2. Q2 技術案の比較
    3. Q3 タスク分配とキュー
    4. Q4 ステートレスと状態管理
    5. Q5 スケーリング
    6. Q6 キャッシュ
    7. Q7 データベース設計
    8. Q8 データ同期と同時アクセス
    9. Q9 ログと監査
    10. Q10 監視指標
    11. Q11 認証と認可
    12. Q12 コストとキャパシティ
    13. Q13 フェイルオーバー
    14. Q14 エラー処理
    15. Q15 対応プラットフォーム
    16. Q16 システムの限界
    17. Q17 トラブルシューティング
    18. Q18 データ保持期間
  4. おわりに

大企業に入ったばかりのエンジニアから、よくこんな質問をされます。「2日で書ける機能なのに、なぜ先に設計書を書いて、何度も会議をしなきゃいけないんですか?」

正直に言うと、私も昔はそう思っていました。でも何度か痛い目を見ました。リリースしてみたら誰も使っていない機能、節約できた額より高くついたクラウドの請求書、誰も理解できないシステムの障害対応で夜中に叩き起こされたこと。そうしてようやくわかったのです。大企業では、コードを書くのはたいてい一番簡単な部分です。難しいのは、書く前に「どこで問題が起きるか」を考え抜くことです。

この記事では、私がシステムを設計するときに自分に投げかける問いを、3つの段階に整理しました。

  1. 設計を始める前に:そもそも何の課題を解決するのかをはっきりさせる
  2. 設計するとき:経営者の視点で判断する
  3. デザインレビューで:よく聞かれる質問と、その裏にあるリスク

どの問いについても「なぜそれを聞くのか」を説明します。問いの裏で何を解決しようとしているのかを理解して、はじめて的確に答えられます。そうでなければ、チェックリストを暗記しているだけです。

この記事を通して使う例

抽象的な話にならないよう、最初から最後まで同じ例を使います。

ある会社に 1,000 人のカスタマーサポート担当者がいます。担当者は通話が終わるたびに、CRM に通話メモを 3 分かけて手入力しています。経営陣は「通話録音の自動要約」機能を作りたいと考えています。電話を切った瞬間に、システムが録音を文字起こしし、要約を作り、CRM に書き込むというものです。


PART 1設計を始める前に

設計を始める前に、どんな問いを考えておくべきかを整理します。

1. なぜこの機能を作るのか?

これは一番飛ばされがちで、でも一番大事な問いです。エンジニアは要件を聞くと、すぐアーキテクチャを考え始めがちです。「どのモデルを使う? Kafka は入れる?」。でも、誰が使うのか、何を解決するのかがはっきりしていないと、技術的には美しいのに誰も使わないものができあがりかねません。

私はこれを3つの小さな問いに分けて考えます。

この機能のユーザーは誰か?

「サポート担当者」は表面的な答えにすぎません。もう一段掘り下げると、実は3種類の人がいます。

3者が求めるものは違い、権限も違います(担当者が他人の通話を見られてはいけない)。これらはすべて、後の設計に直接影響します。

ユーザーのどんな課題を解決するのか?

表面的には「入力時間の削減」です。でも実際に計算してみましょう。1時間に5件、1件あたり3分節約できれば、1時間で15分、1日で2時間の節約です。1,000 人分なら、毎日 2,000 時間分の工数になります。

この数字は重要です。会社がこの機能にいくらまでお金をかけられるかを決めるもので、後でコストを計算するときにも何度も出てきます。

ユーザーは以前どうやっていたのか?

一番見落とされがちで、でも一番救われる問いです。これまで担当者は CRM のメモ欄に手入力し、管理者はクレームを調べるときに録音を聞き直していました。

ここからわかることがあります。要約は最終的に CRM に戻さなければならないということです。独立した Web サイトとして作ると、担当者は2つのシステムの間でコピペすることになります。「入力」が「コピペ」に置き換わっただけで、1か月もしないうちに誰も使わなくなるでしょう。

根本にある課題

「技術的には成功、ビジネス的には失敗」という機能を作らないこと。ユーザーの昔からの習慣は、新しいシステムの制約条件です。

2. どう実装するのか?

機能の中核はどこで動くのか?エンドポイント / クラウド / ローカルサーバー

同じ機能でも、中核をどこに置くかで結果は大きく変わります。

中核の配置通話要約の場合メリット代償
エンドポイント(担当者の PC)各 PC で音声認識モデルを動かす録音をアップロードしないので、プライバシー面で最も有利社用 PC には GPU がなく動かない。1,000 台のモデル更新は悪夢
クラウド録音をクラウドにアップロードして処理開発が最速。スケールはマシンを足すだけ録音には個人情報が含まれ、セキュリティや法務が社外持ち出しを認めない可能性がある
ローカルサーバー(自社データセンター)データセンターに GPU サーバーを置くデータが社外に出ないハードウェアの調達と運用が必要。スケールは調達プロセス待ち

サポートの通話では、お客様がクレジットカード番号や住所を読み上げることがよくあります。だからこの問いは、たいていエンジニアだけでは決められません。まずセキュリティ部門と法務に確認しましょう。作り終わってからではなく、先に聞くのがポイントです。

インターフェースは何か?デスクトップアプリ / モバイルアプリ / Web

担当者は一日中 CRM をブラウザで開いているので、CRM 内の Web プラグインにすればよさそうに思えます。

ただし、それは録音がどこから来るか次第です。電話システム(PBX)がもともと録音しているなら、バックエンドがファイルを取りに行けばよく、フロントエンドは要約を表示する Web プラグインで済みます。しかし電話システムに録音機能がなく、担当者の PC 上のソフトフォンから音声を取り込む必要があるなら、ブラウザではできません。デスクトップアプリが必要になり、それはインストール、自動更新、社用 PC の権限管理への対応を意味します。

小さく見える要件のひとつが、フロントエンド全体の作り方を決めてしまうのです。

主な技術スタックは何か?

音声認識や LLM のエコシステムはほぼ Python なので、音声を処理するワーカーは Python が妥当です。大量の同時リクエストをさばく API サービスは、Go のほうがリソースを節約できるかもしれません。フロントエンドが CRM プラグインなら、その CRM プラットフォームが定める開発フレームワークに従うしかなく、ここに選択の余地はありません。

根本にある課題

中核をどこに置き、インターフェースを何にするかで、データの流れ、コンプライアンス、運用コストが決まります。どれも後から変えにくい決定です。

3. ユーザー規模は?利用頻度は?データ量は?

必ず数字を出しましょう。「たくさんの人が使う」は規模ではありません。「1,000 人、1人あたり1時間に5回、1回 10MB」が規模です。

今回の例で実際に計算してみます。

前提
  • ユーザー:サポート担当者 1,000 人。業務時間(8時間)のみ利用
  • 頻度:1人あたり1時間に約5件の通話
  • ファイル:10分の録音で約 10MB
約 1.4 回毎秒の平均リクエスト数
(1時間あたり 1,000 × 5 = 5,000 回)
約 110 Mbpsアップロード帯域
(1.4 × 10MB ≈ 14 MB/s)
400 GB1日のデータ量
(5,000 × 8時間 × 10MB)
8.8 TB1か月のデータ量
(営業日 22 日で計算)

ここが面白いところです。毎秒 1.4 リクエストなら、マシン1台で余裕です。でも毎月 8.8TB の録音は、1年で 100TB を超えます。

このシステムの課題は QPS ではなく、帯域、ストレージコスト、処理時間です。数字を出さないと、見当違いのところに力を注ぎがちです。たとえば2週間かけて API のパフォーマンスをチューニングするとか。

「業務時間のみ利用」というのも重要な情報です。

根本にある課題

規模がアーキテクチャを決めます。1,000 人のシステムと 100 万人のシステムはまったく別の設計です。数字のない議論は空論にすぎません。

4. システムにはどんな制約があるか?

どの技術にも生まれつきのボトルネックがあります。リリース後に壁にぶつかるより、設計前に知っておくほうがずっといい。

CAP 定理

分散システムでは、一貫性(Consistency)、可用性(Availability)、分断耐性(Partition tolerance)の3つのうち、2つしか同時に満たせません。ただ現実にはネットワークは必ず切れ、分断は必ず起きます。だから本当の選択はこうです。ネットワークに問題が起きたとき、「データが常に正しい」ことと「サービスが常に応答する」ことの、どちらを取るか?

メッセージサイズとタイムアウトの制限

今回の例では特に重要です。録音ファイルが1つ 10MB あるからです。

コンポーネントよくある制限10MB の録音への影響
AWS API Gateway(REST)ペイロード上限 10MB、統合タイムアウトはデフォルト 29 秒ファイルサイズはぎりぎり。10分の録音の文字起こしは確実に 29 秒を超える
AWS Lambda(同期呼び出し)リクエスト / レスポンスのペイロード上限 6MBそもそも入らない
Kafka1メッセージのデフォルト上限は約 1MB入らない
DynamoDB1アイテムの上限 400KB長めの文字起こしなら超える可能性がある

これらの制限がわかれば、設計の方向性は自然に見えてきます。

根本にある課題

設計の途中、あるいはリリース後になって、あるコンポーネントが負荷に耐えられないと判明し、アーキテクチャ全体を作り直す羽目になるのを防ぐこと。

5. ユーザー1人あたりのコストはいくらか?

市場価格はいくらか?自分たちの目標はいくらか?社内ツールでも計算は必要です。経営陣は必ず「既製の SaaS を買う場合」と比べるからです。

前提(数字はすべて例です)
  • 類似の通話要約サービスは、ユーザー1人あたり月額約 30 ドル
  • 自社で1通話あたりにかかる音声認識と LLM 要約のコストは約 0.02 ドル
  • 担当者1人あたりの通話は月に約 880 件(5件 × 8時間 × 22 日)
計算コスト:880 × 0.02 = 17.6 ドル/人/月
ストレージコスト:1人あたり毎月 8.8GB 増加。最初の月はわずかだが、削除しなければ積み上がり続ける
ユーザー1人あたりの月額コスト ≈ 18 ドル〜、しかも毎月増えていく

30 ドルと比べれば余裕がありそうに見えます。でも運用の人件費、遊んでいるマシン、積み上がるストレージを加えると、買った場合と大差なくなるかもしれません。こうなると設計の方向性も変わってきます。

外部の顧客に販売するプロダクトなら、SaaS でよくある粗利率の目標は 70〜80% です。つまりユーザー1人あたりのサービス提供コストは、価格のおよそ2〜3割以内に抑えないと、チームを維持できません。

根本にある課題

作れることと、作るべきことは別です。コストがこの機能が生き残れるかを決め、逆にアーキテクチャも決めます。自前でホストするか、キャッシュを入れるか、データをどれだけ保持するか。

6. 本番品質に到達するまで、どれだけの人員と期間が必要か?

デモが動いた時点で、だいたい半分です。

本番リリースには、監視とアラート、アクセス制御、セキュリティレビュー、負荷試験、エラー処理、オンコール手順書、ドキュメント……がまだ必要です。これらが残りの半分以上の時間を占めることも多いのに、スケジュールから一番抜け落ちやすい部分です。

見積もるときは、作業を2種類に分けます。

明らかなギャップがあり、自分たちで作る必要があるもの

たとえばサポートの通話では、強いなまりや方言、途中で言語が切り替わる会話がよくあり、既製の音声認識では精度が足りないかもしれません。このように「既存の解決策がない」作業は研究的な仕事です。2週間で片づくかもしれないし、3か月たってもまだ調整しているかもしれません。

この部分は必ず切り出して別に見積もり、不確実性をはっきり伝えましょう。通常の開発作業と一緒くたにしてはいけません。

暫定策で埋められるが、後で直す必要があるもの

妥協すること自体は問題ありません。ただし必ずドキュメントに書き、チケットを切り、いつ返済するかを決めておくこと。記録されなかった「暫定」は、最終的に「恒久」になります。

根本にある課題

マネージャーにスケジュールへの妥当な期待を持ってもらい、どんな技術的負債を抱えるのかを全員が把握できるようにすること。

7. 既存のどんなシステムと互換性を保つ必要があるか?

大企業は白紙ではありません。あなたが設計するものは、10年以上動き続けているかもしれない環境の中に置かれます。会社が好む言語、システム、ソフトウェア、取引先は、どれも設計の前提条件です。

会社が好むプログラミング言語

社内の人が Python や Go の専門家ばかりなら、Elixir がこの機能にぴったりだと思っても、よく考えましょう。理由は現実的です。

みんなが慣れた言語を選べば、問題が起きたときにすぐ誰かがレビューし、助けてくれます。

既存のプラットフォームとデータ形式

たとえば社内のデータ基盤が Starburst で、Iceberg 形式が推奨されているとします。それなら通話要約の履歴データも Iceberg テーブルとして保存すべきです。データチームがすぐに分析に使え、別途 ETL を書く必要がありません。

その他のよくある互換性の問題

根本にある課題

運用とコミュニケーションのコストを下げること。システムは書いて終わりではなく、誰かが長く面倒を見続けるものです。会社が「維持できる」技術を選びましょう。


PART 2設計するとき

経営者の視点で判断する

システムを設計するとき、一番大事な意識の切り替えはこれだと思います。この機能を自分で起業した会社だと想像してください。毎月のクラウドの請求書は自宅に届き、夜中に障害が起きたら自分の携帯が鳴ります。

この視点に立つと、自然と次のことが気になってきます。

1. スケーラビリティ:量が増えたとき、マシンを足すだけで済むか?

来年、会社が別のサポートセンターを買収し、担当者が 1,000 人から 3,000 人になったとします。良い設計なら「ワーカーを5台から15台に増やす」で終わりです。悪い設計だと「データベースが耐えられず、2日間止めてデータ移行」になります。

2. 拡張性:新機能を足すとき、作り直しが必要か?

スケーラビリティは「量」の問題、拡張性は「機能」の問題です。リリースから3か月もすれば、管理者は必ずこう言います。「文字起こしがあるなら、ついでに感情分析もできない? クレームの分類も自動でできない?」

文字起こしが終わったときに「文字起こし完了」イベントを発行する設計なら、新機能はそのイベントを購読するだけで追加できます。文字起こし、要約、CRM への書き戻しがひとつの関数にべったり書かれていたら、機能を足すたびにコアの処理に手を入れることになり、変更するたびに壊れるリスクを負います。

3. 許容できるコスト

先ほど計算したユーザーあたりのコストは、設計中に何度も見返しましょう。コンポーネント(キャッシュ、キュー、リードレプリカ)をひとつ足すたびに、自問します。それがもたらすメリットは、その費用に見合うか?

4. 許容できる保守の難しさ

Kafka + Kubernetes + Cassandra を自前で運用すると聞くとかっこいいですが、チームが3人しかいなければ、バージョンアップやノード障害の対応だけでチームの時間が溶けてしまいます。

多くの場合、クラウドのマネージドサービスに少し多めに払って、チームが夜ぐっすり眠れるようにするのは、とてもお得な取引です。

5. レビュアーに選択肢を与える

意外と見落とされるのがこれです。少なくとも2つの案を設計し、長所と短所を比較すること。

なぜか? 案をひとつしか出さなければ、レビュアーは「いい」か「だめ」かしか言えません。しかも心の中で「他のやり方を考えなかったのかな?」と思うはずです。そうなると会議は、各自が頭の中にある案を出し合う場になり、議論は発散します。

2つの案を並べれば、議論は「どのトレードオフを取るか」に絞られます。

A案:クラウドのマネージドサービスB案:自社データセンターでモデルを自前運用
リリースまでの期間約2か月約5か月(GPU 調達を含む)
月額コスト利用量に比例して増える初期のハードウェア投資は大きいが、量が多いと割安
個人情報のコンプライアンス録音をクラウドに出せるか、セキュリティ審査が必要データが社外に出ない
運用負荷低い高い。GPU とモデルの面倒を見る人が必要
スケールの柔軟性高い。いつでも増やせる低い。調達待ち
方言の認識ベンダーの対応状況に左右される自分たちでファインチューニングできる

最後に「どの案を推すか、その理由は何か」を添えます。不採用になった案にも、その理由を一行残しておく価値があります。半年後に「なんで B 案にしなかったの?」と聞かれたとき、ドキュメントが答えてくれます。

(以降のデザインレビューの例では、A 案を推したと仮定します。録音をクラウドに出すことがセキュリティ審査で認められ、まずはクラウドサービスで素早くリリースする、という前提です。)

PoC は道が通じるかの検証であって、システムを作ることではない

これは本当によくある落とし穴です。

PoC(Proof of Concept)が答えるべきなのは、とても具体的な問いです。「この道は通じるのか?」。たとえば:

実際のサポート通話の録音を 50 件用意し(方言、背景ノイズ、怒鳴っているお客様を含む)、音声認識と要約にかけて、精度が 85% に届くかを確かめる。

この PoC にログインもデータベースもきれいな UI も要りません。スクリプトと結果レポートがあれば十分で、1〜2週間で結論が出るべきです。終わったらコードをまるごと捨てても、まったく問題ありません。

よくある失敗パターンはこうです。PoC を作っているうちに UI が付き、データベースが付き、それを経営陣にデモすると「もうできてるじゃないか。来月リリースしよう!」。こうして、アクセス制御も監視もエラー処理もないものが、そのまま本番に出てしまいます。

プロトタイプは、設計が決まった後に、選んだアーキテクチャに沿って作り、少人数の実ユーザーに試してもらうものです。検証するのはフローと体験です。担当者は本当に要約を読むのか? 要約は CRM のどこにあると一番使いやすいのか?

順番はこうです。

PoC で実現性を検証 設計とレビュー プロトタイプで体験を検証 本開発
根本にある課題

最小のコストで最大の不確実性を取り除き、同時に「作りかけのものがうっかり本番に出る」事態を防ぐこと。


PART 3デザインレビューで

デザインレビューは、あなたをいじめる場ではありません。痛い目を見てきた人たちが、システムのリスクを一緒に探してくれる場です。

そして目標はリスクゼロではありません。リスクゼロのシステムなど存在しませんし、仮に存在しても高すぎて作れません。本当の目標は、「知らないリスク」を「知ったうえで引き受けると決めたリスク」に変え、その代償をはっきりさせることです。

たとえば:

以下は、デザインレビューでよく聞かれる質問です。それぞれに「その質問が本当に確認したいこと」を添えました。準備のときにまずそこを考えておくと、答えの方向性がぐっと定まります。

Q1システムはどんな課題を解決するのか?どんな機能を提供するのか?想定規模はどれくらいか?

本当に確認したいこと全員が同じものについて話しているか。

たいてい最初に聞かれる質問です。一言二言で説明できなければ、その後の議論はぼやけてしまいます。良い答えには、ユーザー、価値、数字が入っています。

「1,000 人のサポート担当者が、通話終了後1分以内に要約を受け取れるようにし、1通話あたり3分の手入力をなくす。ピーク時は1時間あたり約 5,000 件、録音は月に約 8.8TB。」

あわせて、このバージョンでやらないこと(Non-goals)も明記しておくのがおすすめです。たとえば「リアルタイム字幕はやらない、感情分析はやらない」。書いておかないと、会議の途中で必ず誰かが「ついでに○○もやるのは難しくないよね?」と言い出します。

Q2どんな技術案があるか?それぞれの長所と短所は?

本当に確認したいこと本当に比較したのか、それとも答えを先に決めてから理由を探したのか。

先ほどの「少なくとも2案」の比較表のことです。レビュアーは比較が公平かを特に見ています。推す案には長所ばかり、もう一方には短所ばかり書いてあれば、それが藁人形だとすぐに見抜かれます。

推す案の短所も正直に書くほうが、かえって説得力が増します。

Q3タスクはどう分配するのか?同期か非同期か?キューは必要か?キューの長さとタイムアウトはどう管理するか?

本当に確認したいことピーク時にシステムが崩れないか、ユーザーはどれだけ待つのか、タスクが消えたり二重に実行されたりしないか。

10分の録音の文字起こしには 30〜60 秒かかるかもしれません。前述のとおり API Gateway はデフォルト 29 秒でタイムアウトするので、同期処理は成り立ちません。フローはこうなります。

担当者が電話を切る 録音を S3 にアップロード タスクがキューに入る ワーカーが文字起こし・要約 CRM に書き戻す 担当者の画面を更新

キューを入れると、続けて必ずこう聞かれます。

Q4中核のワークロードはステートレスかステートフルか?ユーザーの状態はどう記録・保持・復元するか?セッションスティッキーは必要か?

本当に確認したいことマシンを自由に増やしたり減らしたりできるか。マシンが落ちたとき、ユーザーのデータは失われないか。

ステートレスとは、どのマシンでもどのリクエストでも処理できる状態です。マシンが落ちたら別のマシンに替えればよく、スケールするならマシンを足すだけです。ステートフルとは、一部のデータが特定のマシンのメモリにしかない状態で、そのマシンが落ちるとデータも消えます。

例:ワーカーが「この録音をどこまで処理したか」をメモリに持っていると、オートスケーリングでマシンが削除されたとき、その通話は最初からやり直しになります。正しくは、進捗をデータベースや S3 に書き、ワーカー自体は状態を持たないようにします。

やっかいなのは、担当者に「要約ができました」と知らせる部分です。WebSocket でプッシュするなら、接続そのものが特定のマシンに紐づくので、本質的にステートフルです。よくある方法は2つあります。

復元については、担当者が再接続したとき、フロントエンドが call_id でデータベースから最新の状態を取得します。「さっきの接続が何を覚えていたか」には頼りません。

Q5ユーザーとデータが増えたら、システムをどうスケールするか?ステートレスな水平スケールか、シャーディングか?何の指標でスケールさせるか?

本当に確認したいこと成長したとき「マシンを足す」で済むのか、「設計し直す」必要があるのか。

成長には2種類あり、分けて考える必要があります。

ユーザーが増える(リクエストが増える):ステートレスな水平スケール

担当者が 1,000 人から 3,000 人に増えても、API とワーカーがステートレスなら、マシンを足すだけで解決します。

データが増える(テーブルが大きくなる):パーティション、ホット/コールド分離、シャーディング

1年後、データベースには数千万件の通話記録があり、管理者の「過去1年のクレームをすべて」という検索がどんどん遅くなります。このとき API のマシンを足しても意味がありません。ボトルネックはデータベースです。次の順で検討します。

  1. 月単位でパーティションを切り、検索では必要な月だけをスキャンする
  2. 1年を超えたコールドデータは Iceberg に移し、Starburst でクエリする(ちょうど社内の既存基盤です)
  3. 書き込み量に本当に耐えられなくなってから、シャーディングを検討する

シャーディングで一番重要なのはシャードキーの選び方です。たとえば「日付」をシャードキーにすると、今日のデータはすべて同じシャードに入り、そのシャードだけが常に一番熱く、他のシャードは暇を持て余します。分けていないのと同じです。「サポートセンター ID」や「担当者 ID」で分けるほうがずっと均等になります。シャードキーは一度間違えるとほぼ変えられないので、レビュアーは細かく突っ込んでくるのが普通です。

スケールのトリガーになる指標

多くの人は直感的に CPU を使いますが、今回の例ではそれは間違いです。ワーカーはほとんどの時間、外部の音声認識 API の応答を待っています(I/O バウンド)。CPU は 20% なのに、キューにはすでに 2,000 件たまっている、ということが起こります。CPU をトリガーにしたら、いつまでたってもスケールしません。

より良い指標は次のとおりです。

Q6キャッシュは必要か?TTL はどれくらいにするか?データの不整合をどう防ぐか?

本当に確認したいことキャッシュは「一貫性と引き換えに速度を得る」もの。何を手放したのか、わかっているか?

まず前提として、すべてのシステムにキャッシュが必要なわけではありません。1,000 人規模の社内システムなら、データベースだけで十分さばけるかもしれません。キャッシュを1層足すことは、データ不整合の原因を1つ増やすことです。まず計測し、必要だと確認できてから入れましょう。

本当に必要なら、データの性質で決めます。

後者は、書き込み時にキャッシュを能動的に消す(データベースを更新したら対応するキャッシュキーを削除する)ようにし、TTL は最後の保険として使います。

もうひとつよくある落とし穴がキャッシュの一斉失効(キャッシュアバランシェ)です。大量のキーが同時に書き込まれ、TTL も同じだと(たとえば朝9時に一括ロードし、TTL はすべて1時間)、10 時ちょうどに全キャッシュが一斉に失効し、トラフィックがすべてデータベースに押し寄せます。対策は TTL にランダムな揺らぎ(ジッター)を加えることです。たとえば 55〜65 分にして、失効タイミングをばらけさせます。

Q7データベースはどう設計するか?CAP のトレードオフは?読み書き分離、シャーディング、バックアップとリストア、マルチ AZ、I/O キャパシティは?

本当に確認したいことデータベースはシステムの中で最も後から変えにくい部分。最初に考え抜いておかないと、後の代償が一番大きい。

CAP のトレードオフ

同じシステムの中でも、データごとに違う選択をして構いません。「1通話につき正式な要約は1つだけ」という対応関係には強い一貫性が必要ですが、統計レポートは結果整合性で十分です。

読み書き分離

管理者の重いレポートはリソースを食うので、リードレプリカで実行し、担当者の書き込みを遅くしないようにします。ただしレプリカには遅延(レプリケーションラグ)があります。担当者が要約を保存した直後に画面がレプリカから読むと、「あれ、保存されてない?」となります。だから自分が書き込んだばかりのデータはプライマリから読むようにします。

バックアップとリストア

「バックアップがある」ことは「リストアできる」ことと同じではありません。レビュアーはきっとこう聞きます。実際にリストアしたことはあるか? 2TB のリストアに何時間かかるか? その間システムはどうするのか?

リハーサルしていないバックアップは、たいてい障害が起きてから、あるテーブルがバックアップ対象から漏れていたとか、リストアに 12 時間かかるとかが判明します。

マルチ AZ

あるデータセンター(アベイラビリティゾーン)で停電やネットワーク断が起きたとき、データベースは別のデータセンターに自動で切り替わるか? 代償としてコストはおよそ倍になるので、「1時間止まった場合の損失」がその費用を上回るかを見極めます。

I/O キャパシティ

クラウドのディスクには IOPS の上限があります(たとえば AWS gp3 のベースラインは 3,000 IOPS)。よくあるのが、夜間のバッチレポートが IOPS を使い切り、オンラインの書き込みまで遅くなるケースです。データベースが落ちたように見えるのに、CPU はほとんど暇。I/O の指標を見ていないと、原因究明に長い時間がかかります。

Q8データ同期はどう設計するか?複数人の同時アクセスをどう制御するか?

本当に確認したいこと2人が同じデータを同時に編集したとき、誰かの変更が黙って消えないか。

シナリオ

担当者がある通話の要約を修正している最中に、管理者が同じレコードにメモを追加します。管理者が先に保存し、担当者が後から保存すると、管理者のメモは上書きされて消え、しかも誰も気づきません。これをロストアップデートと呼びます。

よくある解決策:

システム間のデータ同期はまた別の問題です。要約は CRM に書き戻す必要がありますが、CRM の API がたまたま落ちていたら?

Q9ログはどう収集するか?どんなエラーを分析できるか?システムの異常イベントを検索できるか?ユーザー操作の監査ログは残すか?

本当に確認したいこと何か起きたとき、何が起きたのかを突き止められるか。

シナリオ:担当者から「昨日の午後の通話に要約がない」と報告が来ます。ログがただのテキストの羅列で、何の ID でもつながっていなければ、何百万行ものログから針を探すことになります。

基本原則をいくつか挙げます。

監査ログ(Audit Log)はまた別物です。通話録音にはお客様の個人情報が含まれます。セキュリティ監査や情報漏えいの調査では、必ず「誰が、いつ、どの録音を聞き、どの要約をダウンロードしたか」を聞かれます。こうしたログは通常のログとは分けて保存し、改ざんできないようにし、保存期間は社内規程や法令に従って決めます。

Q10どんな指標を監視するか?CPU、メモリ、ディスク、ネットワーク、リクエスト数、キャッシュヒット率、コネクションプールのサイズ、レイテンシは?

本当に確認したいことユーザーより先に、システムの異常に気づけるか。

指標は2つの層に分けて考えます。

これらの指標がなぜ大事かがわかる、実際に起きる例をいくつか紹介します。

Q11認証と認可はどう動くか?ユーザーが他人のデータにアクセスするのをどう防ぐか?どのログイン方法に対応するか?アカウントはどう登録するか?

本当に確認したいことセキュリティホール、それも最もよくあって最も深刻な種類のもの。

まず区別しておきましょう。認証(Authentication)は「あなたは誰か」、認可(Authorization)は「あなたは何をしてよいか」です。

最もよくある脆弱性は IDOR と呼ばれるものです。担当者が自分の通話を見ようと /calls/12345/summary を開き、好奇心で URL を 12346 に変えてみたら、他人の通話が見えてしまった、というものです。

フロントエンドでボタンを隠すだけでは意味がありません。すべての API で、この人がこのデータを見る権限を持っているかをバックエンドで確認する必要があります。たとえば、自分の通話であるか、あるいは管理者でかつ自分のチームメンバーの通話であるか。

ログイン方法:社内システムなら、会社の SSO(SAML / OIDC で Azure AD や Okta と連携)にそのままつなぎましょう。独自に ID・パスワードを作る最大の問題は、社員が退職して AD のアカウントが無効になっても、あなたのシステムのアカウントは残っていて、ログインできてしまうことです。

アカウント登録:社内システムは通常セルフ登録を開放せず、AD グループから同期します(たとえば SCIM 経由)。人事異動があれば、権限も自動で追従します。

Q12システムのコストはいくらか?どれだけのトラフィックに耐えられるか?サービス単位あたりどれだけ処理できるか?

本当に確認したいことシステムのキャパシティについて「実測した数字」を持っているか、それとも推測にすぎないか。

「サービス単位」とは、ワーカー1台、Pod 1つがどれだけ処理できるかのことです。この数字は負荷試験で測る必要があり、これがあってはじめてスケールとコストを計算できます。

負荷試験の結果:ワーカー1台で、10分の録音を毎分 12 件処理できる
通常のピーク:5,000 件/時 ≈ 83 件/分 → 7 台必要
障害への余裕(2台落ちても耐える)→ 9 台
月初の3倍のトラフィック:約 250 件/分 → 21 台以上必要

台数に単価を掛ければ月額コストになり、それをユーザー数で割れば、先ほどの「ユーザー1人あたりのコスト」の話に戻ってきます。

あわせて、耐えられる量を超えたらどうなるかも明確にしておきます。キューで待たせて遅くなるのか? レート制限で拒否するのか? それとも文字起こしだけに縮退するのか?

Q13各コンポーネントのフェイルオーバーの仕組みは?復旧にどれくらいかかるか?

本当に確認したいことどのコンポーネントもいつか壊れる。壊れたとき、ユーザーには何が見えるのか?

よく使われる指標が2つあります。

コンポーネントを一つひとつ挙げて、順に答えていくのがおすすめです。

コンポーネント障害のシナリオフェイルオーバーの方法復旧時間
API サーバー1台が落ちる複数台をロードバランサーの後ろに置き、自動で切り離すほぼ気づかない
ワーカー処理の途中で落ちるタスクがタイムアウト後にキューへ戻り、別のワーカーが引き継ぐその通話が数分遅れる
データベースプライマリが落ちるマルチ AZ で自動切り替え約1〜2分。その間の書き込みはリトライできる必要がある
録音ファイル(S3)1つのデータセンターの障害S3 自体が複数 AZ に保存し、耐久性が非常に高いRPO は 0 でなければならない。録音は絶対に失えない
外部の音声認識 / LLM APIベンダーのサービス停止タスクをキューに残して復旧を待つか、予備のベンダーに切り替えるベンダー次第。その間、担当者は手入力で対応

最後の行が一番忘れられがちです。外部依存が壊れたとき、自分たちには直しようがありません。できるのは、あらかじめ代替策を考えておくことだけです。また、要約は作り直せますが、録音は失ったら終わりです。だから両者の RPO の要件はまったく違います。

Q14エラー処理の方針は?入力の検証や制限は必要か?出力のページングは必要か?失敗したらリトライするか?回数と間隔は?

本当に確認したいこと入力は決して信用せず、呼び出しは必ず失敗すると想定しているか。

入力の検証

シナリオ

担当者が電話を切り忘れて一晩中録音し、3GB の録音ファイルができてしまいます。ワーカーが読み込もうとしてメモリ不足(OOM)で落ち、タスクがキューに戻り、別のワーカーが拾ってまた落ちる……と次々に落ちて、キュー全体が詰まります。処理するものを落とし続けるこうしたメッセージを Poison Message(毒メッセージ)と呼びます。

だから入力には必ず制限を設けます。

出力のページング

管理者が「今月のすべての通話」を検索し、API が 10 万件を一度に返した結果、API はタイムアウトし、ブラウザは固まります。一覧系の API には必ずページングを入れましょう。データ量が多い場合は OFFSET(後ろのページほど遅くなる)ではなく、カーソルベースのページングがおすすめです。

リトライ戦略

Q15どのプラットフォームに対応するか?レスポンシブデザインは必要か?

本当に確認したいこと対応プラットフォームがひとつ増えるたびに、開発・テスト・保守のコストも増える。本当に必要か?

「対応しない」プラットフォームを明記することも大切です。たとえば「スマホからの録音アップロードには対応しない」。書いておかないと、リリース後にバグとして報告されます。

Q16システムにはどんな限界があるか?どんな状況で到達するか?

本当に確認したいこと自分のシステムの限界がどこにあるか、そこにぶつかったら何が起きるかを知っているか。

設計前に聞いた「制約」は外部技術の制約でした。ここで聞かれているのは自分たちのシステムの限界です。それぞれについて、「どんな状況で到達するか」と「到達したときにシステムがどう振る舞うか」をはっきり書きます。

限界いつ到達するか到達したときの振る舞い
1ファイル最大 50MB(約 50 分)テクニカルサポートの通話は1時間を超えることが多い処理を拒否し、「手動で記録してください」と表示
処理量の上限は毎分約 250 件月初に請求書が届いた後キューで待機し、要約の生成が遅れる
LLM API の毎分トークン上限ピーク時間帯429 を受けたらバックオフしてリトライ
主要言語のみ対応方言が強い通話や他言語の通話「認識の確信度が低い、要人手確認」とマーク

こうして書いておけば、夜中のインシデントは「ドキュメントに書いてある既知の振る舞い」になり、サポートの管理者も事前に対応方法を把握できます。

Q17システムの問題をどう調査するか?ユーザーとシステムの状態について、何を記録しているか?

本当に確認したいことシステムの「デバッグしやすさ」を設計段階から考えていたか、それとも問題が起きてからログを足しているか。

実際の調査の流れを通して、どんな情報が必要かを見てみましょう。

オペレーターの佐藤さんから報告:「10時32分の通話の要約が空っぽです」
  1. 佐藤さんのユーザー ID と時刻から、その通話の call_id を特定する
  2. call_id でトレースを見る:アップロード成功、キューにも届き、文字起こしも完了しているが、文字起こしの長さが 0
  3. 録音ファイルの情報を見る:ファイルサイズは正常だが、サンプリングレートが 8kHz。前日までは 16kHz だった
  4. 当時のシステム状態を見る:電話システムが前夜にアップグレードされ、デフォルトの録音形式が変わっていた。音声認識は非対応の形式を受け取り、エラーを出さずに空の結果を返していた
  5. 結論:モデルが壊れたのではなく、上流の形式が変わった。しかも自分たちのシステムは「黙って失敗」していた。これ自体も直すべき問題で、文字起こしが空ならエラーとして扱い、アラートを出すべき

この流れをたどれるようにするには、事前に次の情報を記録しておく必要があります。

特に大事なのがバージョン情報です。「クライアントの 2.3.1 だけで問題が起きる」「電話システムのアップグレード後から壊れ始めた」といった結論は、バージョンを記録していなければ永遠にたどり着けません。

Q18データの保持期間はどれくらいか?システムとして許容できるか?

本当に確認したいことデータを消さなければコストは際限なく増え、長く持ちすぎれば法的リスクと漏えいリスクも増える。

先ほどの数字を思い出してください。録音は毎月 8.8TB。永久に保存すれば、1年後には 100TB、3年後には 300TB を超えます。S3 Standard を 1GB あたり月 0.023 ドルでざっくり見積もると(実際の価格はリージョンによる)、1年後には録音の保存だけで毎月 2,000 ドル以上かかり、しかも増え続けます。

よくあるのは、アクセス頻度に応じてデータを階層化する方法です。

経過期間保存先用途
30 日以内標準ストレージ(S3 Standard)担当者や管理者が頻繁に聞き直す
30 日〜1年低頻度アクセス/アーカイブストレージクレームで揉めたときに参照。単価はずっと安い
保持期間を過ぎたもの自動削除(ライフサイクルポリシー)コストと個人情報のリスクを下げる

保持期間はエンジニアだけで決めるものではありません。法務やセキュリティ部門と一緒に決めましょう。

最後に、よく見落とされる細かい点をひとつ。削除は完全に。録音を消しても、バックアップ、ログ、そこから派生した文字起こし、要約、検索インデックスが残っていたら、実質的には消していないのと同じです。


WRAP-UPおわりに

たくさんの問いを並べましたが、すべてで満点を取る必要はありません。目的は設計書を分厚くすることではなく、次の3つを実現することです。

課題を理解する

誰が使うのか、何を解決するのか、以前はどうしていたのか、規模はどれくらいか、コストはいくらか。

選択肢を示す

少なくとも2つの案を用意し、トレードオフを正直に比較し、推す理由を書く。

リスクをさらけ出す

どのリスクなら引き受けられて代償は何か、どれは絶対に妥協できないか。

大企業では、ひとつの設計判断が複数のチームと何年分もの運用に影響します。1〜2週間かけてこれらの問いを考え抜けば、リリース後に何か月も地雷を踏み続けずに済みます。

次に設計書で手が止まったら、まず自分がレビュアーになったつもりで、これらの問いを自分に投げかけてみてください。答えられたものは設計書に書く。答えられなかったもの、それこそがまだ考え抜けていないところです。

← ブログに戻る Arlo AI のオープンソースプロジェクトを見る