arch-event-sourcing について
イベントソーシングを検討する開発者向けのアーキテクチャスキルです。追記専用のイベントログを信頼できる情報源とする設計を説明し、再生、スナップショット、バージョン管理、運用上の考慮点を扱います。
主な機能
- 01追記専用イベントログ
- 02イベント再生による状態復元
- 03スナップショットの利用
- 04イベントスキーマの進化
- 05CQRSとの連携
活用シーン
- 01監査履歴の保持
- 02過去時点の状態確認
- 03複数の読み取りモデル生成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill arch-event-sourcingインストール後、Claude Code で/arch-event-sourcingを入力して読み込まれたか確認します。
詳細
1行でまとめると
状態を変更するイベントのシーケンスを、信頼できる唯一の情報源として永続化します。イベントを再生することで現在の状態を導出します。イベントログは追記専用で不変であり、権威ある情報源です。
このスキルを使う場面
- 変更履歴を完全に記録することが求められる監査や規制上の要件がある場合。
- 「何が起きたか」という観点で業務を捉えるのが自然な場合(銀行取引、請求の調整、サプライチェーンのイベントなど)。
- 時点を指定したクエリ(「日付 X 時点の状態は何だったか」)に回答する必要がある場合。
- 同じデータから複数のプロジェクションが必要で、手作業で維持するよりイベントから具体化するほうが簡単な場合。
- 読み取りに正規のイベントストリームとは異なる形が必要な場合は、CQRS(
arch-cqrsを参照)と自然に組み合わせられます。
このスキルを使わない場面
- ドメインがイベントという考え方に沿っていない場合 — データモデルを無理にイベントの形にするコストが、メリットを上回ります。
- 現在の状態があれば十分で、履歴をほとんど参照しない場合 — CRUD のほうがシンプルです。
- チームが結果整合性、再生のセマンティクス、イベントのバージョン管理に不慣れな場合 — 運用上の負担が非常に大きくなります。
- マイクロサービスが流行していて、どこかで読んだからという理由で「イベントソーシング」を採用する場合 — それは理由になりません。
主な内容
イベントストア。 各イベントに集約 ID、シーケンス番号、タイムスタンプを付与した、追記専用のログです。書き込みには append(events) を使い、特定の集約の読み込みには eventsFor(aggregateId) を使います。
状態の再構築。 集約の現在の状態は、そのイベントを畳み込んで得られます。
state = events.fold(initial) { acc, event -> apply(acc, event) }
新しいコマンドを処理するには、イベントを読み込み、再生して現在の状態を取得し、コマンドを実行して、新しいイベントを追記します。メモリ上の状態は一時的なものであり、ディスク上のイベントが真実です。
スナップショット。 長期間にわたって使われる集約(数年分のイベントがある場合)は、最初から再生すると時間がかかります。スナップショットとは、イベント N 時点の状態を定期的に保存したものです。読み込み時にはスナップショットと N 以降のイベントを使います。スナップショットは最適化であり、信頼できる唯一の情報源ではありません。信頼できる情報源はあくまでイベントです。
イベントのバージョン管理。 イベントは永続します。そのスキーマは、将来のバージョンとの互換性を保ちながら進化させる必要があります。手法は次のとおりです。
- 追加のみの変更 — 新しいフィールドは任意項目とし、必須にはしません。
- アップキャスター — 読み込み時に古いイベントバージョンを現在の形式に変換するコードです。
- 緩やかなスキーマ(許容的な解析を行う JSON) — コンパイル時の安全性と引き換えに柔軟性を得ます。
CQRS との組み合わせ。 イベントソーシングによる書き込みからは、読み取りモデルにプロジェクションするイベントが自然に生成されます。イベントソーシングを採用する本番システムの多くは、イベントストリームを直接クエリしにくいため、クエリに CQRS を使います。
運用上の考慮事項。
- イベントストアの可用性は非常に重要です。信頼できる唯一の情報源だからです。
- コミットする前に、ツール(再生、プロジェクションの再構築、スキーマのマイグレーション)を用意しておく必要があります。プロジェクトの途中で作るのは大変です。
- ストレージは単調に増加します。計画を立ててください。
- スナップショットのない、数百万件のイベントを持つ集約は、処理に苦労します。
判断のヒューリスティクス
- 監査、時点指定のクエリ、複数のプロジェクションが本当に必要な集約に限って、イベントソーシングを適用します。何にでも一律に適用してはいけません。
- スナップショットの間隔は調整可能な値です。まずは 100~500 件から始め、再生性能を見て調整します。
- イベントスキーマは公開 API として扱い、バージョン管理し、決して壊さないでください。
- 本番環境でイベントソーシングに依存する前に、運用ツール(再生、再構築、マイグレーション)を整備します。
アンチパターン
- システム全体への反射的なイベントソーシングの適用。 大半のサブドメインには不要です。通常は、強い監査要件があるコアドメインに限って選択的に適用します。
- 変更可能なイベント。 履歴を「修正」するために過去のイベントを編集することです。パターンの根幹を損ないます。「訂正」するには、補償イベントを追記します。
- DTO としてのイベント。 「フィールドが変更された」以上の意味を持たないイベントです。イベントは、過去形で、業務上の意味があるドメインイベントにするべきです。
- 高頻度で使われる集約をスナップショットなしで再生すること。 コマンドの処理に数秒から、数十秒かかるようになります。
- アップキャスターなしでスキーマを破壊すること。 古いイベントが読み取れなくなり、実質的に履歴が失われます。
関連項目
arch-cqrs— イベントのプロジェクションから読み取りモデルを構築します。arch-event-driven— コンテキスト間のコミュニケーションとしてのイベント(多くの場合、同じイベントです)。ddd-domain-event— 戦術レベルのイベントの概念です。ddd-aggregate— イベントソーシングを採用した集約は、コマンドの処理の一環としてイベントを生成します。
参考文献
- Khononov、『Learning DDD』第7章(イベントソースドメインモデル)。
- Vaughn Vernon、『Implementing Domain-Driven Design』— 第8章に、標準的なJavaでの解説があります。
- Greg Young、イベントソーシングに関する講演やエッセイ(基礎的な資料)。