ユースケース: メインフレームのモダナイゼーション、運用データレイヤー
業種: 金融サービス
MongoDB 製品: MongoDB Atlas、MongoDB 集計パイプライン、Change Streams
ソリューション概要
コアバンキングは銀行を実行するエンジンです。カスタマー、アカウント、残高、支払い、および財務イベントを管理し、すべてのダウンストリームチャンネル、製品、およびレポート作成システムはそれに依存します。
この中心性があるため、コアのモダン化は非常に困難です。多くの銀行は、断片化されたデータ、固定されたスキーマ、バッチするウィンドウ、および点対点の統合に依存しています。新しい製品、チャンネル、および規制要件が発生するにつれ、複雑さは通常増大します。
ソリューションは?Banking Industry Architecture Network (BIAN)と MongoDB を使用してコアバンキングをモダン化します。
BIAN はビジネス アーキテクチャを定義します。MongoDB は、コンポーザブルなイベント駆動型のドメイン所有のデータ プラットフォームとして実装します。
BIAN: ターゲットアーキテクチャ
Banking Industry Architecture Network (BIAN) は、機能をサービスドメインとしてモデル化する銀行業界標準である BIAN フレームワークを定義します。
銀行操作をサービスドメインとして定義すると、各チームには責任の範囲が明確に定義され、次のような結果が得られます。
より明確な境界のあるコンテキスト: 各サービスドメインには定義された範囲と目的があります。
データの所有権を明確化する: 1 つのドメインが各ビジネスオブジェクトとそのデータを所有します。
API の境界を明確にする: ドメインは共有データベースアクセスではなく、標準契約を介して交流します。
意味的なズレが少ない: 共有される語彙により、チームとシステム間で期間がコンシステントに保たれます。
MongoDB: 実装データプラットフォーム
MongoDB は BIAN サービスドメインモデルを実際に実装します。各銀行のニーズは、ネイティブな MongoDB 機能にマップされます。
document model は、カスタマー、アカウント、およびネストされた KYC レコードなどの階層的な銀行データに適しています。
複数のドキュメントに対する ACID トランザクションは、1 回のコミットで同期の資金移動を実行します。
チェンジストリームは、ポーリングなしでフィンシャルイベントをリアルタイムで伝播します。
スキーマ検証ツールと集計パイプラインは、データに近い会計ルールを強制します。
このソリューションでは、デリバリーパイプラインを妨げることなく、コアバンキングを減速的にモダン化する方法を示します。
参照アーキテクチャ
このソリューションは 3 つの FastAPI バックエンド サービスに分割されています。各サービスはエンドツーエンドの資金の流れにおいて独自の責任を持っています。
アカウントサービスは、カスタマーとアカウントの状態を所有します。これは、当事者参照データと当座預金機能の BIAN に準拠した操作を公開します。
トランザクションサービスは、支払いの開始と支払いの実行を所有します。操作上の支払い結果を 1 つの MongoDB ACID transaction として同期的に書き込みます (write)。
レッジャー サービスは会計パイプラインを所有しています。実行されたトランザクションに対して非同期的に反応し、補助元帳とジャーナルの記入に必要な財務面のレコードを導出します。
この分離はアーキテクチャの中心です。支払い実行、アカウント状態、会計の真実性は関連していますが、同じ懸念事項ではありません。このデザインにより、データリニアージを介してこれらの関係が維持され、各サービスは独自の境界内で進化できるようになります。
図 1BIAN と MongoDB を使用したハイレベルアーキテクチャ: コアバンキング。
チャンネルはアプリケーションとサービスの境界を通じて入力されます。
ユーザーは Web UI を介してソリューションを操作します。フロントエンドはチャンネル レイヤーとして機能し、パスベースルーティングを介して、リクエストを関連するバックエンド サービスにルーティングします。サービスは BIAN スタイルのエンドポイントとなる接続されたデバイスを公開します。このため、インターフェース レイヤーはデータベース構造の漏洩を防ぎ、ビジネス機能に合わせて維持されます。
アカウントサービスは、カスタマーとアカウントの真実を所有しています。
アカウントサービスは、
customersコレクションとaccountsコレクションの読み取りと書き込み (write)を行います。カスタマーマスターデータ、KYC 関連のアカウントコンテキスト、残高、アカウントライフサイクル操作の正しい情報源として機能します。これは、アカウントと残高の取得の同期読み取りパスです。トランザクション サービスは支払いを同期的に実行します。
支払いが開始されると、トランザクションサービスはそれを 1 つの MongoDB 複数ドキュメント ACID transaction として処理します。このソリューションでは、その作業単位で、ソースアカウント残高の引き落とし、宛先アカウント残高のクレジット、トランザクションレコードの挿入、支払いステータスの更新、および関連する通知またはステータス変更の書き込み (write)を 1 つのコミットで行います。
運用アカウントではトランザクションフローで残高が即座に更新され、元帳フローでは総勘定元帳が非同期で更新されます。総勘定元帳は、転記時間枠の終わりに、バッチで、個別に転記されます。
MongoDB は会計伝播のイベントソースになります。
公開台帳パスは変更をポーリングしないため、ソリューションの外部メッセージバスに依存しません。代わりに、公開台帳サービスは MongoDB の変更ストリームを通じて
transactionsコレクションを監視します。新しく挿入されたすべてのトランザクションは、非同期の会計プロセシングの trigger となります。これは、運用実行と財務プロセシングの間のアーキテクチャの引き継ぎです。
図 2レッジャー サービス。
クリックして拡大します先計サービスのステージ 1 では、会計境界オブジェクトが書き込み (write) されます。
最初の公式帳レジャーワーカーはトランザクション変更ストリームを消費し、支払いごとに 1 つの
ledgerEventドキュメントを書き込み (write)ます。このドキュメントには、デビットとクレジットの公式帳レジャーの項目、ダウンストリームで必要な記入コンテキストを含むビジネス イベントの会計解釈が含まれています。イベントが書き込まれる前に、ワーカーはデビットとクレジットの脚がバランスしていることを確認します。このコントロールが重要なのは、
ledgerEventsがフローの最初の不可変な会計コレクションであるためです。ここに書き込まれたデータは、ダウンストリームのsubLedgerEntriesとjournalEntriesに伝播される前に正確である必要があります。アーキテクチャー的に、
ledgerEventsは支払いドメインと財務ドメインの境界コレクションです。支払いの速度を会計処理の速度から切り離しながら、元の支払いへの系譜を維持します。Ledger Service のステージ 2 では、エンティティレベルの会計エントリをプロジェクトします。
2 番目の元帳ワーカーは
ledgerEventsを監視し、各イベントを 2 つのsubLedgerEntries(デビットとクレジット) にプロジェクトします。これらのエントリを ACID transaction でまとめて書き込み (write)、イベントのバランスが取れていること、両方の GL アカウントがチャートの有効な投稿リーブであることを再検証します。この段階では、カスタマーのステートメントと日中の位置ビューに使用されるエンティティレベルの会計真実が作成されます。
レッジャー サービスのステージ 3 は総合元帳を書き込みます。
バッチするワーカーは、保留中のサブレジャーエントリを定期的に照合し、バランスの取れた
journalEntriesにロールアップします。照合が失敗した場合、サイクルは投稿をスキップします。成功した場合、ワーカーはジャーナルエントリを書き込み (write)、結果のジャーナル識別子をソースレコードにスタンプし直し、投稿ステータスを変更します。リアルタイム支払いの場合でも、総合元帳はバッチで書き込まれます。GL ではなく、副元帳が日中残高の正確なソースです。スキーマは、トランザクションごとに書き込みを選択する機関のための REALTIME 書き込みモードをサポートしますが、このソリューションでは標準的な業界の実行とコンシステントでバッチする GL 書き込みを使用します。
プラットフォームは、端から端まで双方向に追跡可能性を維持します。これにより、デザインの監査が可能になります。
データフローは、業務レイヤーと会計レイヤーの両方向で完全に追跡可能です。支払いは、支払いからトランザクション、そして
ledgerEvents、subLedgerEntries、最後にjournalEntriesと移動します。すべてのジャーナルエントリは、同じチェーンを通じて元の支払いに戻すことができます。この両方向の系譜は、パイプライントレースUI、監査可能性、およびダウンストリームのコンシューマーのアーキテクチャの明確さをサポートします。
データモデルアプローチ
データモデルは、サービスと同じアーキテクチャ分離に従っています。各コレクションは、フローの中で特定の業務上または会計上の目的を勤めるために存在します。
運用コレクション
customersカスタマー マスター レコードとネスト化された KYC コンテキストを保存します。accounts当座状態を保存し、バランスの真実性のソースとして機能します。paymentsPENDING や SETTLED などの支払い指示とライフサイクル状態を保存します。transactions支払いの事実を保存し、全序パイプラインのイベントソースとなります。
これらのコレクションは、アーキテクチャの操作側面をサポートします。カスタマーとアカウントのワークフローを直接提供し、アカウントおよびトランザクションサービスによって同期的に更新されます。
会計コレクション
glAccounts勘定科目チャートを保存し、書き込みできる内容を検証します。ledgerEventsトランザクションごとに 1 つの会計境界レコードを保存します。subLedgerEntriesエンティティレベルの借方とクレジットの記入を保存します。journalEntriesバランスの取引された総合元帳エントリを保存します。
データフロー
フローは慎重であり、以下の手順は、コレクションがプロセス フローにどのように参加するかを要約しています。
支払い指示は payments に到着します。
同期決済実行は、結果となる実行済みトランザクションファクトを
transactionsに書き込み (write)、運用口座残高を更新します。トランザクションの変更ストリームは公開取引パイプラインをトリガーします。
元帳の取り込みステージは、トランザクションごとに 1 つの
ledgerEventを書き込み (write)ます。公開取引イベントには、両方の脚と、ダウンストリームパスを決定する投稿モードが含まれます。
サンプル ドキュメント: 公開台帳イベント
{ "eventId": "LE-20260415-000042", "idempotencyKey": "PAY-20260415-0042", "groupId": "GRP-20260415-000042", "eventType": "PAYMENT_PRINCIPAL", "debitLeg": { "glAccountCode": "1001", "controlAccountCode": "1000", "amount": { "$numberLong": "100000" }, "currency": "USD", "entityReference": { "entityType": "ACCOUNT", "entityId": "ACC-001234" } }, "creditLeg": { "glAccountCode": "2100", "controlAccountCode": "2000", "amount": { "$numberLong": "100000" }, "currency": "USD", "entityReference": { "entityType": "ACCOUNT", "entityId": "ACC-001235" } }, "postingMode": { "type": "BATCH" }, "postingStatus": "PENDING", "sourceReference": { "sourceCollection": "transactions", "sourceId": "PAY-20260415-0042", "sourceSystem": "LEDGER_PIPELINE" } } プロジェクションステージは、イベントごとに 2 つの
subLedgerEntriesを書き込み (write)ます。プロジェクションワーカーは、1 つの
ledgerEventを 2 つのsubLedgerEntriesに分割し、各脚に 1 つずつつつて、ACID transaction でまとめて書き込みます。各々は完全な書き込み脚として単独で存在します。journalEntryIdはgl_batchが本物の ID をスタンプするまで""センチネルを携帯します。サンプル ドキュメント: 補助元帳入力
{ "subLedgerId": "SLE-20260415-000042-D", "idempotencyKey": "LE-20260415-000042:DEBIT", "controlAccountCode": "1000", "side": "DEBIT", "amount": { "$numberLong": "100000" }, "currency": "USD", "periodCode": "2026-04", "status": "POSTED", "journalEntryId": "", "entityReference": { "entityType": "ACCOUNT", "entityId": "ACC-001234" }, "sourceReference": { "sourceCollection": "ledgerEvents", "sourceId": "LE-20260415-000042", "sourceSystem": "LEDGER_PIPELINE" } } クレジットレッグを調整するのは2番目のドキュメントで、同じ
sourceId、反対のsideとcontrolAccountCode、entityId:ACC-001235です。journalEntryId($gt: "") のパーシャルインデックスは、バッチが実際のジャーナル ID を入力するまで両方を除外します。バッチパスは、調整された
journalEntriesを書き込みます。バッチはサブレジャーエントリを集計し、バランスの取れた行が埋め込み配列に存在する 1 つのジャーナルにまとめます。
サンプルドキュメント:ジャーナルエントリ
{ "journalId": "JNL-20260623-EOD-1001", "idempotencyKey": "BATCH-20260623-EOD:1000:2026-06", "periodCode": "2026-06", "journalType": "LEDGER_EVENT_POSTING", "status": "POSTED", "totalAmount": { "$numberLong": "1000000" }, "entries": [ { "lineNumber": 1, "accountCode": "1000", "side": "DEBIT", "amount": { "$numberLong": "1000000" }, "currency": "USD" }, { "lineNumber": 2, "accountCode": "2000", "side": "CREDIT", "amount": { "$numberLong": "1000000" }, "currency": "USD" } ] } 検証者は会計不変量を強制します
3 つのコレクション バリデーターは会計ルールをデータベースにプッシュします。このため、サービス レイヤーをスキップする書き込み (write)でも、会計帳簿が破損することはありません。
ledgerEventsバリデーターにはビジネス フィールドが必要であり、postingStatusを既知のenumにロックします。_LEDGER_EVENTS_VALIDATOR = {"$jsonSchema": { "bsonType": "object", "required": ["eventId", "idempotencyKey", "groupId", "occurredAt", "valueDate", "eventType", "debitLeg", "creditLeg", "postingStatus", "sourceReference", "mappingVersion"], "properties": { "postingStatus": {"bsonType": "string", "enum":["PENDING", "POSTED", "FAILED"]}, "debitLeg": _LEG_SCHEMA, "creditLeg": _LEG_SCHEMA, }, }} subLedgerEntriesバリデータはsideをDEBITまたはCREDITに、statusをPOSTEDまたはFAILEDにロックし、すべてのドキュメントでjournalEntryIdを必要とします。""センチネルはgl_batchが本物の ID をスタンプするまでこれを満たすため、エントリがこのライフサイクルの外にあることはありません。journalEntriesバリデータは、Pacioli バランス不変量を直接強制します。つまり、デビット行の合計はクレジット行の合計と等しくなる必要があり、これは書き込み (write)ごとに$exprでチェックされます。_JOURNAL_BALANCE_VALIDATOR = {"$expr": {"$eq": [ {"$sum": {"$map": {"input": {"$filter": {"input": "$entries", "as": "e", "cond": {"$eq": ["$$e.side", "DEBIT"]}}}, "as": "e", "in": "$$e.amount"}}}, {"$sum": {"$map": {"input": {"$filter": {"input": "$entries", "as": "e", "cond": {"$eq": ["$$e.side", "CREDIT"]}}}, "as": "e", "in": "$$e.amount"}}}, ]}} 会計コレクションはアーキテクチャの財務面をサポートします。これらは、会計またはトランザクション サービスによって直接書き込まれるものではなく、操作イベントから派生されます。
このチェーンにより、操作スピードと会計管理の両方を実現できます。支払い実行は完全な GL 投稿を待ちませんが、すべての支払いは監査可能な会計トレールに解決されます。
MongoDB が自然に適している理由は何ですか?
カスタマーとアカウントのデータは階層的であり、時間とともに変化します。支払いレコードには、レールとチャンネルによって変数メタデータが含まれます。关連する会計事実は、単一のビジネスドキュメントにグループ化されます。
MongoDB では、サービスがデータを生成および消費する方法に合わせて、アカウント状態、ライフサイクルの詳細、KYC コンテキスト、支払いの事実、および埋め込み投稿行を保存できます。リレーショナル モデルで必要となる繰り返しのフラット化と再組み立てを回避できます。
ソリューションのビルド
このセクションでは、MongoDB を使用して BIAN を実装する方法と、Leafy Bank BIAN ソリューションをレプリケートする方法を説明します。完全な実装ガイドについては、リポジトリをクローンし、Github README. の設定手順に従ってください
MongoDB で BIAN を実装する
Leafy Bank BIAN ソリューションをレプリケートする
リポジトリをクローンし、設定手順に従ってください。
Github リポジトリに移動し、README の手順に従って、次の操作を実行します。
前提条件の準備
リポジトリをクローンし、依存関係をインストールします
MongoDB データベースをプロビジョニングします
バックエンドサービスを構成する
フロントエンドプロキシを構成する
レッジャー インデックスおよび検証者を作成します
サンプルデータをシードする
サービスを開始します
エンドツーエンドの流れを検証します
コンテナ化されたパスを実行します (必要な場合)
キーポイント
このソリューションライブラリでは、次の方法を学びました。
BIAN フレームワークを使用してターゲット アーキテクチャを定義します: サービス ドメインにより、より明確なビジネス境界、データの所有権、および API コントラクトが作成されます。
支払い実行と元帳投稿を分離してください: アーキテクチャは操作状態を同期的に更新し、会計状態を非同期的に更新します。
両方のフローで MongoDB を使用: ACID トランザクション、変更ストリーム、バリデータ、および集計パイプラインは、1 つのプラットフォームでパスワードなしをサポートします。
ledgerEvents をコントロール境界として扱う: データが不可変の財務フローに入る前に、バランスの取引内容を検証します。
プロセス フローに関するモデル コレクション: 各コレクションは個別のステージをサポートし、アーキテクチャ全体でリニエージを維持する必要があります。
漸進的なモダン化: 価値の高いドメインから開始し、コアを完全に置き換えることなくプラットフォームを拡張します。
作成者
Doina Brestoiu
Kiran Tulsulkar
Ainhoa Mugica
Andrea Alaman Calderon