SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Developers Summit 2025 セッションレポート

整合性を守り抜く非同期処理アーキテクチャ設計

【14-D-7】データの整合性を保つ非同期処理アーキテクチャパターン

 非同期処理を用いたシステム設計では、「処理の流れが追いづらい」「変更が困難」「整合性の担保が難しい」といった課題がつきまとう。本セッションでは、AI家計簿アプリ「ワンバンク(旧B/43)」の開発を手がけるスマートバンクの木田悠一郎氏が、実践から導き出した4つの設計指針を紹介。イベントのモデリング、非同期制御のパターン、Transactional Outboxによる整合性の担保、そしてスキーマ設計まで──複雑な業務フローと向き合うエンジニアにとって、すぐに活かせる知見が満載だ。

正しく保存するためのモデリング

 「データ整合性を保つ非同期処理アーキテクチャパターン」というタイトルでセッションを始めたのは、スマートバンクのエンジニア・木田悠一郎氏。担当するのは、カード決済や後払いといった金融領域の開発・運用だ。発表では同社のカード発行処理を例に、非同期処理における設計課題とその解決パターンが紹介された。

株式会社スマートバンク ソフトウェアエンジニア 木田 悠一郎氏
株式会社スマートバンク ソフトウェアエンジニア 木田 悠一郎氏

 スマートフォンアプリからカード発行を申請し、物理カードが発行・発送され、手元に届いたのちにアプリ上で利用開始する。こうした一連の業務プロセスは、複数の「イベント」で構成される。そして、これらのイベントは非同期処理によってつながっているため、「処理の流れが把握しづらい」「変更が難しい」「データ整合性の担保が困難」といった課題が起きがちだと木田氏は説明する。

カード発行における業務フローの一例。非同期処理が絡む場面も多い
カード発行における業務フローの一例。非同期処理が絡む場面も多い
非同期処理を取り入れたシステム開発で直面しやすい3つの課題
非同期処理を取り入れたシステム開発で直面しやすい3つの課題

 こうした課題を乗り越えるための設計方針として、木田氏は次の4つのポイントを提示する。

  • イベントを正しく保存する
  • イベント間の整合性を保つ
  • データベースとメッセージキューの整合性を保つ
  • メッセージのスキーマを定義する

 まず解説されたのは、「イベントを正しく保存する」ためのモデリング手法だ。

 「非同期処理の前後には、必ずといっていいほど何らかのデータ保存が発生する」と木田氏。だからこそ、まずは構造をしっかり設計することが大切になるという。その際に重要になるのが、「イベント」と「リソース」を分けて捉えるという考え方だ。

 たとえば、「受注日」「発送日」「入金日」など、時間とともに一度だけ発生する事象は「イベント」に分類される。一方で、従業員や商品など、持続的に存在する情報は「リソース」として区別されるべきだ。「イベントとリソースをごちゃ混ぜにすると、更新処理が煩雑になり、テーブル構造も不明瞭になります」と木田氏は語る。

イベントにひもづく日付は「過去に起きた出来事」の発生日を示す
イベントにひもづく日付は「過去に起きた出来事」の発生日を示す

 スマートバンクにおけるカード発行処理を例に、木田氏は4つのモデリングパターンを紹介する。

【前提:カード発行に関わる一連の処理】

  • カード発行申請:ユーザーID、カード名義、申請日時など
  • カード発行:カードIDなど
  • カード発送:配送先住所など
  • カード利用開始:利用開始日時など

【モデリングパターンとその特徴】

パターン1:直前のイベントIDを持つ

 各イベントに、直前のイベントIDを持たせて順序を明示する方法。外部キー制約により厳格な順序管理が可能になる。一方で、全体の流れをたどるにはイベントを一件ずつ追う必要がある。

各イベントに直前のIDを持たせて順序を管理する「パターン1」の設計例
各イベントに直前のIDを持たせて順序を管理する「パターン1」の設計例

パターン2:最初のイベントIDを持つ

 すべての後続イベントに「カード発行申請」など最初のイベントIDを持たせる方式。イベント分岐にも対応しやすく、関連データを一括取得しやすい。ただし、順序の保証はアプリケーション側に委ねられる。

すべてのイベントに最初のIDを持たせて関連性を保つ「パターン2」の設計例
すべてのイベントに最初のIDを持たせて関連性を保つ「パターン2」の設計例

パターン3:ロングタームイベントを親に持つ

 すべてのイベントの親となる「カード注文」などのテーブルを用意し、現在のステータスをその中に保持する設計。業務の進捗をひと目で把握でき、複雑な業務フローにも対応しやすい。

イベントを包括する親テーブルで状態を管理する「ロングタームイベント」設計
イベントを包括する親テーブルで状態を管理する「ロングタームイベント」設計

パターン4:ツリー構造(経路列挙モデル)

 イベントのIDをスラッシュで連結し、履歴を1カラムに格納する方法。たとえば「申請ID/入金待ちID/カード発行ID」のように、階層構造を1行で持つことができる。RubyではancestryというGemを使えば簡易に実装可能。

履歴をスラッシュ区切りで保持する「ツリー構造」モデルの設計例
履歴をスラッシュ区切りで保持する「ツリー構造」モデルの設計例

 いずれのパターンにおいても、イベント同士の関連づけが鍵になる。「フローに分岐がある場合や、処理の進行に応じて複雑化していく場合には、どの方式を選ぶかがシステムの柔軟性を左右する」と木田氏は話す。

 一方で、現場でしばしば見かけるNGパターンとして「全部盛りモデル」が挙げられた。これは、複数の概念や責務を1つのテーブルに詰め込んでしまう設計であり、「一見楽に見えても、更新処理が煩雑になり、変更や拡張に弱くなる」と警鐘を鳴らす。

 「テーブルを4つに分けると逆に複雑になるのでは?」という懸念に対しても、木田氏は「分けることで仕様変更に対応しやすくなる」と説明。たとえば、「複数のカード発行申請に1つの発行を紐づけたい」といった要件変更にも柔軟に対応できるようになるという。

 パフォーマンスやクエリの複雑さについても、「高いパフォーマンスが求められるケースは実はそこまで多くない」と補足。むしろ、更新対象テーブルを分けることでロック競合を防ぎ、保守性が高まる場面の方が多いと述べた。

次のページ
イベント間の整合性をどう担保するか

この記事は参考になりましたか?

Developers Summit 2025 セッションレポート連載記事一覧

もっと読む

この記事の著者

夏野 かおる(ナツノ カオル)

 博士。本業は研究者。副業で編集プロダクションを経営する。BtoB領域を中心に、多数の企業案件を手がける。専門はテクノロジー全般で、デザイン、サイバーセキュリティ、組織論、ドローンなどに強みを持つ。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山出 高士(ヤマデ タカシ)

雑誌や広告写真で活動。東京書籍刊「くらべるシリーズ」でも写真を担当。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

CodeZine編集部(コードジンヘンシュウブ)

CodeZineは、株式会社翔泳社が運営するソフトウェア開発者向けのWebメディアです。「デベロッパーの成長と課題解決に貢献するメディア」をコンセプトに、現場で役立つ最新情報を日々お届けします。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/21421 2025/10/28 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング