Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TypeScriptで設計する 堅牢さとUXを両立した非同期ワークフローの実現

TypeScriptで設計する 堅牢さとUXを両立した非同期ワークフローの実現

2025/11/23 TSKaigi Hokuriku2025 に登壇した際の資料です。
https://hokuriku.tskaigi.org/

複数のドメインコンテキストで構成されるWebシステムは、コンテキストを跨ぐ更新を行う同期APIがパフォーマンスの悪化や障害の連鎖を招き、ユーザー体験を損ねがちです。本セッションでは、非同期で実行されるコンテキスト間データ連携を設計する知識を体系的にまとめつつ、特にTypeScriptの"型=契約"を核にしたイベント駆動+Sagaパターンを採用した場合の実戦知を共有します。

X: https://twitter.com/moeka__c

Avatar for Matsumoto Moeka

Matsumoto Moeka

November 23, 2025
Tweet

More Decks by Matsumoto Moeka

Other Decks in Programming

Transcript

  1. moeka__c m-moeka 松本 萌花 Matsumoto Moeka 経歴 SIerでBEエンジニア → 2022年5月〜

    
  アセンド株式会社に4人目エンジニアとして入社
  現在はリードプロダクトエンジニア。 0->1案件に単身でぶち込まれがち。 なんだかんだ好きなのはBE。 型パズルってやりだすと結構ハマる。 最近犬を飼い始めた(超可愛い)。
  2. DF | 4.91 /day L T | 2 hours MTTR

    | 24 min CFR | 2.6% Full-Stack TS で1エンジニアの生産性を高め、
 プロダクトエンジニアがオーナーシップを持ってオールインワン SaaS を開発する Product Engineering 技術 デザイン 事業 Full-Stack TypeScript Full-Stack TypeScript のプロダクト組織
  3. 支払い管理 車両管理 労務管理 • • • ドライバー アプリ 請求管理 運行管理

    案件管理 業務間連携 協力会社 依頼 テナント間連携 発注 テナント間連携 荷主企業 ロジックスはオールインワンSaaSとして、運送業の中心・運行業務をハブとして、
 様々な業務モジュールが連動しあい、全体の業務進行を支えている。 オールインワン SaaS の特性
  4. 労務管理 • • • ドライバー アプリ 請求管理 運行 案件管理 業務間連携

    発注 テナント間連携 荷主企業 請求 請求書へ集約 入金確認 案件 配車 運行終了 運賃確定 発注 依頼 実績確認 支払い 請求書確認 修正 修正 例えば、案件 → 請求連携の場合 オールインワン SaaS の特性 テナント、コンテキストを越えた多くの連携 強い整合性要件(金額ズレ不可、バッチ処理不可)
  5. オールインワン SaaS の特性 同一ブランドで提供するからこそ
 業務間でもシームレスなUX ユーザーの声などから素早い改善
 深く・正しく・シンプルに業務を実現 他の業務に及ぼさず
 深さと拡張性を追求できる 疎結合・高凝集なモジュール設計

    業務データを相互に連携。
 基幹業務を最高効率で回すための
 即時性と整合性が高い情報連携設計 vs. 複雑な業務 vs. 多種多様な業務 プロダクト要求 求められる システム要件 ポイントソリューションではなくオールインワンであることが競合優位性。 両立の難易度は高く、事業のスピードは早いが、適切に取り組まねばならない。 エンジニアには設計時のバランス感覚が求められる。
  6. オールインワン SaaS の特性 同一ブランドで提供するからこそ
 業務間でもシームレスなUX ユーザーの声などから素早い改善
 深く・正しく・シンプルに業務を実現 他の業務に及ぼさず
 深さと拡張性を追求できる 疎結合・高凝集なモジュール設計

    業務データを相互に連携。
 基幹業務を最高効率で回すための
 即時性と整合性が高い情報連携設計 vs. 複雑な業務 vs. 多種多様な業務 プロダクト要求 求められる システム要件 ポイントソリューションではなくオールインワンであることが競合優位性。 両立の難易度は高く、事業のスピードは早いが、適切に取り組まねばならない。 エンジニアには設計時のバランス感覚が求められる。 プロダクト初期は同期 API で対応 コンテキストは分けてなるべく疎結合にしつつ
 整合性担保のため 1 つのトランザクションで同期的にデータ連携
  7. 同期 API の壁 事業拡大に伴い、連携の種類が多様に&技術特性要件が変化した結果、
 現状のアーキテクチャが限界を迎えた システム課題 事業 変化 詳細 概要

    業務内で取り扱うデータの変化 テナント間の情報連携 大量データ 営業所が全国に。
 CSが面倒見きれないので
 処理状態やエラーFBのUX向上が急務 変更通知、変更履歴 整合性要件の複雑さ イベントが下請けチェーンを連鎖する 同期APIでのバルク処理でロック地獄に よいUXを実現するためのコードが複雑化 全ての要求を愚直に実現するのはカオス 下請けのテナント含めて整合性を取る必 要性など、同期的な設計の限界
  8. 整合性 堅牢性 UX 拡張性 整合性・堅牢性 データの正しさ バグの少なさ コードの見通しの良さ UX・拡張性 パフォーマンスの良さ

    処理状況のわかりやすさ サービスの独立性 整合性とUXを両立するアーキテクチャに刷新を目指す アーキテクチャの刷新を決定
  9. Q1. ワークフロー|Sagaパターン コレオグラフィ方式 ▪ 状態管理 ▪ 拡張性 シンプルな連携や疎結合を優先したい連携向き 各サービスが自分のローカル状態(イベント履歴)のみ持つ 進行状態は発生したイベント群を追うしかなく


    補償トランザクションも合わせた全体整合性の把握は難しい 新サービスを「イベントをトリガに参加させる」だけ 疎結合でスケーラブル https://learn.microsoft.com/ja-jp/azure/architecture/patterns/saga
  10. シナリオ① DB成功 イベント送信失敗 データはあるのに 通知が届かない ↓ 不整合 データがないのに
 通知が届いてしまう ↓

    誤作動 シナリオ② DB成功 イベント送信失敗 Q2. イベント発行 | 課題 DBトランザクションとイベント送信のどちらか一方が失敗する可能性がある
  11. 先程の課題たち イベント発行の信頼性担保 メッセージの重複処理対応 呼び出し関係制御 トレーサビリティ確保 の、他にも… エラー時の補償処理設計 Sagaの複数化/並列実行/呼出順の入れ替わり インフラ自体が途中で落ちたらどうなる? 互換性のないメッセージの


    バージョンアップをしたいときはどうする?                  ...などなど 許容できる不整合範囲を見極め、 総合的な判断の上で様々な対策が必要。 vs 1つ1つの判断をメンバーで共有して
 実装で徹底し切る&その後知識を
 継承して保守し続けるつらさと直面する 非同期処理の技術的複雑性をどう制御するか
  12. ① フローの全体像を『 付の状態マシン+イベント』として表現 型 ② 設計上重要な『EventSourcing』と『Outboxパターン』を で強制 型 ③ 忘れがちなサービスの重複呼出防止の仕組みを

    で強制 型 ④ イベントペイロードのバージョンアップを 安全に行う 型 今回は 4 つ事例を紹介 非同期処理の技術的複雑性を”型”で制御する
  13. コマンドの実行(実線部分) [to 請求書] 請求反映コマンド [to 案件] 請求反映承認/棄却の追跡コマンド   ※この棄却追跡が補償トランザクション イベントの検知(点線部分) [from

    案件] 運賃確定イベント [from 請求書] 請求書変更承認/棄却イベント [from 案件] 承認/棄却処理完了イベント ① 『フローの全体像』を型で表現 請求連携プロセスを実現するサーガを制御するオーケストレータの処理は
 下記のようになる