
Fintech
イベント
マガジン
技術ブログ
こんにちは。メルペイの Balance Team で Tech Lead をしている @kobaryo です。この記事は「 Merpay & Mercoin Tech Openness Month 2026 」の18日目の記事です。 はじめに Balance Team では お客さまの残高やポイントを扱うマイクロサービスをはじめ、債権を取り扱う Debt Service も管理しています。先日公開された @imamu さんの「 事業者請求払いのための与信管理マイクロサービスの設計 」で、与信を扱う Credit Service を中心に事業者請求払いの設計が紹介されましたが、本記事ではその中で取り上げられた「債権を任意の軸で集計する仕組み」を Debt Service 上でどのように表現したのかについて紹介します。 事業者請求払いでは、与信管理のために「与信枠ごとの未返済債権」を高速に取り出したい、また請求のために「請求先ごとの債権の一覧」を把握したい、という2つのニーズが生まれます。お客さまや事業者ごとの残債を管理する既存のテーブル DebtAccount はお客さまや事業者を表す ID という単一の軸に縛られており、この2つの独立した軸を同時に管理できませんでした。この壁を越えるために、「DebtAccount は債権の操作ログ DebtLog を集計したビューである」という発想から DebtAccountView を設計しました。1つの DebtLog を異なる軸で集計された複数のビューに畳み込むことで、与信枠軸と請求先軸を独立して管理でき、将来の新しい集計軸も最小限の変更で追加できます。 Debt Service が管理する「債権」とはなにか 事業者請求払いでは、我々が取引のたびに代金を立て替え、後からまとめて事業者に請求します。この立替金の記録が 債権(Debt) です。Debt Service はメルペイの中で債権を一元管理するマイクロサービスで、事業者向けのみでなくお客さま向けのメルペイのクレジットなど、複数のサービスから呼ばれる下位レイヤーとして機能します。 各 Debt は「誰の(CustomerId)」「何の種別の(DebtType)」「いくらの(Amount)」立て替えかを保持します。DebtType は決済の種別や精算方法を区別するための分類で、お客さま向けの月次清算を表すものや事業者向けの請求書払いを表すものなど複数の種別が存在します。 個別の Debt が増えていくと、「ある事業者の現時点での残債はいくらか」を素早く知りたい場面が増えます。Debt を1件ずつスキャンして合算するアプローチは、Debt の件数に比例して計算コストが大きくなるため、取引のたびに現在の残債が与信上限を超えないかをリアルタイムで確認するには向きません。そのために DebtAccount というテーブルでお客さまや事業者ごと、かつ種別ごとに残債を保持しています。Debt の作成や返済が発生するたびに DebtLog (債権の操作ログ)が記録され、それに応じて DebtAccount の Amount が更新される仕組みです。 「1口座1軸」という壁 DebtAccount の設計はシンプルです。Unique key (CustomerId, DebtType) によって、「この事業者の、この種別の残債はいくらか」という問いに即座に答えられます。お客さま向けのメルペイのクレジットなど既存のユースケースではこれで十分対応できました。 請求書払いプロジェクトでは、この設計に2つの新しい要件が加わりました。1つは与信管理の要件です。詳細な説明は上述の @imamu さんの記事 に委ねるのですが、今回店舗や部門ごとなど1事業者が複数の与信枠を持てる設計を目指しています。そのため、与信枠を扱う Credit Service は決済フローの中で「ある与信枠に紐づく残債」をリアルタイムに取得できなければなりません。もう1つは請求の要件です。Invoice Service は請求先の軸でまとめた債権から請求書を発行するため、「ある請求先に紐づく債権の一覧」を取得できなければなりません。与信の軸(与信枠)と請求の軸(請求先)は完全に独立しており、1つの債権が両方に同時に紐づきます。またこれらの軸はどちらも CustomerId すなわち既存の事業者IDと独立しているため、既存の DebtAccount を用いて集計することはできません。 2つの要件はそれぞれ性質が異なります。与信計算は決済フローの中でリアルタイムで行われ、応答時間が Debt の件数に依存してはならないため、与信枠の軸でも既存の DebtAccount と同じ「1行参照で残債がわかる」事前集計が必要です。請求の要件は残債の集計ではなく、明細の作成や債権の返済のためにどの債権がどの請求先に属するかという紐づけを保持しておくことです。ただし後々事業者向けに請求額を確認できるダッシュボードを提供したいなど、請求先軸でも事前集計する必要が出てくるかもしれません。またこれらに追加して3軸目がこの先登場しないとも限りません。このように考えた場合、我々に必要なものは多軸で残債を集計でき、かつその軸と債権を紐付けておく汎用的な仕組みでした。 1つの操作を複数の軸で同時に集計する DebtAccountView この仕組みを実現するヒントは、DebtAccount の性質そのものにありました。DebtAccount は「口座」という名前のとおり実体を持つ台帳のように見えます。しかし、すべての事実は DebtLog に記録されており、DebtAccount はその DebtLog を (CustomerId, DebtType) 軸で集計し、現時点の残債を1行に集約したビューです。この捉え方に立つと、「同じ DebtLog を別の軸で畳み込んだビューが複数あってもよい」という発想が生まれます。これが DebtAccountView の設計の直感的な出発点です。 口座を分割するのではなく、集計の軸を並列に増やすというのが、設計の方向です。DebtLog は従来 DebtAccount という1つの集計ビューだけを更新していました。ここで、1つの DebtLog が既存の DebtAccount に加えて任意の数のビューを同時に更新できるようにしました。 各 DebtAccountView は既存の DebtAccount と同じ物理構造を持つ集計テーブルです。DebtAccount の設計思想をそのまま踏襲しているため、DebtAccountView 専用の新しい運用パターンを考える必要はありません。従来「1 DebtLog が1 DebtAccount を更新する」ところを「1 DebtLog が1 DebtAccount + N 個の DebtAccountView を更新する」に拡張した形です。 3つのテーブルが作る台帳の構造 この仕組みを支えるのが3つのテーブルです。 DebtAccountViews (集計した残債)、 DebtAccountViewItems (Debt と DebtAccountView の所属関係)、 DebtAccountViewLogs (Debt Account View の変動履歴)がそれぞれの役割を担います。この機能に関わる主要な3テーブルのスキーマを示します。 -- 集計した現在の残債 CREATE TABLE DebtAccountViews ( DebtAccountViewId STRING(100) NOT NULL, ViewKeyType INT64 NOT NULL, -- 1=請求先 ID, 2=与信付与先 ID, ... ViewKeyId STRING(MAX) NOT NULL, -- 指定した ViewKeyType の中の ID CustomerId INT64 NOT NULL, DebtType INT64 NOT NULL, Amount INT64 NOT NULL, ) PRIMARY KEY(DebtAccountViewId); CREATE UNIQUE INDEX DebtAccountViewsByViewKey ON DebtAccountViews(ViewKeyType, ViewKeyId, DebtType, CustomerId); -- どの Debt がどの DebtAccountView に属するか(請求書作成時に使用) CREATE TABLE DebtAccountViewItems ( DebtAccountViewId STRING(100) NOT NULL, DebtId STRING(100) NOT NULL, ) PRIMARY KEY(DebtAccountViewId, DebtId); -- 残高変動の履歴 CREATE TABLE DebtAccountViewLogs ( DebtAccountViewLogId STRING(100) NOT NULL, DebtAccountViewId STRING(100) NOT NULL, DebtAccountLogId STRING(100) NOT NULL, -- DebtLog に対応する DebtAccountLog(DebtAccount の変動ログ)を DebtAccountView に紐付けることで、間接的に DebtLog と紐付けている ) PRIMARY KEY(DebtAccountViewLogId); 上流マイクロサービスは、債権を作成する際に ViewKeyType (集計の軸)と ViewKeyId (ある集計軸における集計ID)を指定すれば、あとはその債権が返済・取消など操作されるたびに自動的に DebtAccountView が更新されます。また軸の種類を増やす際は単に ViewKeyType の種類を増やすだけで十分です。 今後の展望 現状の実装では、一度の債権の操作で更新する DebtAccountView が多くなる、すなわち集計軸が増えていくと、債権操作のレイテンシが上昇してしまいます。そこで考えられる拡張が ViewKeyType ごとに更新の同期・非同期を切り替えられる設計です。初期実装では全 ViewKeyType をデータ書き込みと同じトランザクションで同期的に更新していますが、将来同期的に反映しなければならない与信枠などの軸は同期的に、債権の変動と集計する間にタイムラグがある請求先の軸は非同期で反映するという拡張を予定しています。 また今回事業者請求払いのために DebtAccountView を設計しましたが、toB toC 問わず与信を分割したり与信を付ける先と請求する先が異なる任意のビジネスに適用できます。また、設計の本質は変動ログをピックアップし集計する汎用的なものであるため、債権に限らず残高やポイントを管理する Balance Service に導入して利用することも考えられます。 おわりに DebtAccountView は、「1つの債権に複数の集計軸を持たせたい」という要件から生まれた機能です。既存の DebtAccount 設計をベースに、「1 DebtLog → N View を更新する」という拡張を汎用的かつシンプルに実現することにこだわりました。また将来のユースケースや拡張も考え抜けたことは、実装を通じて得た達成感の一つです。 事業者請求払いはメルペイの Payment Platform としてまだ進化の途中にあります。与信管理、債権管理、請求、精算という一気通貫のプラットフォームを、各サービスの責務を保ちながら積み上げていくことは、技術的にもドメイン的にも自信を持って面白いと言えます。もしこうした課題に興味を持っていただけたら、ぜひ Balance Team やメルペイの採用・インターン情報も覗いてみてください。この記事が、Fintech や決済基盤のドメイン設計に興味を持つエンジニアにとって何らかのヒントになれば幸いです。 次の記事は yogawaさん と haoyuさん です。引き続きお楽しみください。 Appendix: 採用しなかったその他の選択肢 既存の事業者IDのみでなく与信枠軸や請求先軸など任意の単位での集計を実現する手段として、DebtAccountView 以外にもいくつかの案を検討しました。 1つ目は与信枠ごとに DebtAccount を分割し、請求先の情報は Debt に持たせる方法です。現状のスキーマの延長線上で実装することができとてもシンプルですが、請求先情報という Debt ドメインに関わりが深くない情報を列に直接追加するのはあまりに汎用的でありません。 2つ目は DebtAccount を親子関係で分割する案です。事業者全体の DebtAccount を親として、その子は与信枠の軸で分割、さらにその子は請求先の軸で分割するといったものです。DebtAccount を分割するための軸という概念を追加しそこに与信枠軸や請求先軸を入れるので、1つ目の案よりは汎用的です。しかし与信枠の軸と請求先の軸は互いに独立しているので、与信枠の軸での集計は効率よく行えるものの、請求先の軸での集計は依然効率よく行えません。加えて、与信枠軸や請求先軸のみでなく効率良く集計する必要のある3軸目が登場した場合に、1つ目の案とこの2つ目の案は対応することができません。 3つ目は Debt Service 内でなく、上流サービス側で集計を持つ方法です。Credit Service が与信枠ごとの残債を管理し、Invoice Service が請求先ごとの集計を管理する設計です。しかし Debt Service を使うサービスが増えるたびに、同じ集計ロジックを各サービスが個別に実装することになります。Debt Service 内で集計済みの情報を管理すれば、債権の元データを唯一の情報源として、各サービスへの変更通知なしに信頼性の高い集計を一元的に提供できます。この仕組みを Debt Service に置くことは、将来債権を取り扱う新しいビジネスが高パフォーマンスな集計を必要としたとき、プラットフォームとして即座に応えられる基盤への投資でもあります。
本稿は、2026 年 06 月 04 日に公開された “ Gain visibility into DDoS attacks with flow logs in AWS Shield Advanced ” を翻訳したものです。 これまで、分散型サービス妨害 (DDoS) 攻撃のトラフィックを再構成するには、事後に複数のデータソースを組み合わせる必要がありました。 AWS Shield Advanced の攻撃フローログは、これを変革します。攻撃中にトラフィックのメタデータをキャプチャするため、送信元の特定、緩和策の検証、既存の分析パイプラインへのデータ投入が可能になります。 Shield は、他の AWS フローログと同じ CloudWatch Logs の配信インフラストラクチャを使用して、 Amazon Simple Storage Service (Amazon S3) 、 Amazon CloudWatch Logs 、または Amazon Data Firehose にログを発行します。そのため、すでに使用しているモニタリングおよび分析ツールに直接組み込めます。 この記事では、 Shield Advanced 攻撃フローログ が DDoS イベント中にどのようにメタデータをキャプチャするか、フローログエントリの各フィールドが何を意味するか、そして保護対象リソースに対してフローログを有効化および設定する方法を説明します。 DDoS 攻撃がアプリケーションに与える影響 DDoS 攻撃は、アプリケーションをトラフィックであふれさせ、ユーザーが利用できない状態にします。インフラストラクチャ層の攻撃は帯域幅を飽和させ、接続テーブルを枯渇させるため、パケットロスやタイムアウトが発生します。 Shield Advanced は、 Amazon CloudFront ディストリビューション、 Elastic Load Balancing のロードバランサー、 Amazon Route 53 のホストゾーン、 AWS Global Accelerator の標準アクセラレーター、および Elastic IP (EIP) アドレスに対して、攻撃を検出して緩和するマネージド型の DDoS 保護サービスです。対応範囲の詳細については、 AWS Shield Advanced のドキュメント を参照してください。 Shield Advanced では、まず EIP 保護を対象としたインフラストラクチャレイヤーの攻撃フローログが提供され、その後、対応するリソースタイプが順次拡大される予定です。 主な利点 フローログは、攻撃を以下のようなさまざまな観点から理解するのに役立ちます。 トラフィックパターンの再構築 – 攻撃発生後にログをクエリすることで、トラフィック量、送信元の分布、プロトコルの構成比を分析でき、CloudWatch の集約メトリクスだけに頼る必要がなくなります。 攻撃元の特定 – srccountry および location フィールドは、トラフィックがどこから発生し、どの AWS エッジロケーションに入ってきたかを示します。 緩和動作の検証 – action フィールドは、Shield が各フローに対して行った処理を記録します。 ログは Amazon S3、CloudWatch Logs、または Data Firehose に送られます。その後、新しいインフラストラクチャをデプロイすることなく、 Amazon Athena (Amazon S3 内のデータを分析するためのサーバーレスのクエリサービス) でクエリしたり、サードパーティのセキュリティ情報イベント管理 (SIEM) プラットフォームにルーティングしたり、 CloudWatch Logs Insights (対話型のログ分析機能) のクエリを構築したりできます。 攻撃フローログがキャプチャする内容 ログレコードは、送信元と送信先の IP アドレスおよびポート、プロトコル、パケット数とバイト数、Shield Advanced が実行したアクション、TCP フラグをキャプチャします。また、トラフィックが入ってきた AWS イングレスロケーションと、可能な場合はトラフィック送信元の 2 文字の国コードも含まれます。ログは 5 分間隔で書き込まれ、攻撃の進行中および終了後に利用できます。 ファイルの最大サイズは 75 MB です。5 分間のウィンドウ内にファイルがその上限に達した場合、そのファイルはクローズされて転送され、新しいファイルが開始されます。フローログは JSON、プレーンテキスト、W3C、Parquet の出力形式に対応しており、以下のフィールドを含みます。 フィールド 説明 protection_arn Shield 保護の Amazon リソースネーム (ARN) event_timestamp ログ生成のタイムスタンプ version フローログのバージョン番号 srcaddr 送信元 IP アドレス dstaddr 送信先 IP アドレス srcport 送信元ポート dstport 送信先ポート protocol プロトコル番号 packets 集約ウィンドウ内のパケット数 bytes 集約ウィンドウ内のバイト数 starttime 集約ウィンドウの開始時刻 endtime 集約ウィンドウの終了時刻 action Shield が実行したアクション location AWS イングレスロケーション sampling_rate パケット処理中に使用されたサンプリングレート tcp_flags パケットの TCP フラグ srccountry トラフィック送信元の 2 文字の国コード Shield Advanced 保護対象リソースに対するフローログの設定方法 以下の手順では、Shield Advanced 保護を任意のログ送信先に接続する CloudWatch Logs 配信リソースの作成方法を説明します。 前提条件 フローログを設定する前に、以下を準備してください。 有効な Shield Advanced サブスクリプション 少なくとも 1 つの既存の Shield Advanced 保護 CloudWatch Logs 配信リソースを作成するための AWS Identity and Access Management (IAM) 権限 ( logs:PutDeliverySource 、 logs:PutDeliveryDestination 、 logs:CreateDelivery ) フローログには標準の CloudWatch Logs のベンドログ料金が発生し、送信先リソース (S3 バケットのストレージ、CloudWatch Logs のロググループのストレージ、または Firehose のデータ処理) には別途料金が発生します。トラフィックの多いリソースでフローログを有効化する前に、 CloudWatch の料金ページ のベンドログの項目と、選択した送信先サービスの料金を確認してください。 仕組み ログ配信には 3 つのオブジェクトが必要です。 DeliverySource – ログを生成する Shield Advanced 保護を表します DeliveryDestination – ログの送信先 (Amazon S3、CloudWatch Logs、または Amazon Data Firehose) を表します Delivery – ソースと送信先を接続します この 3 オブジェクトモデルにより、複数のソース間で送信先を再利用したり、配信パイプラインを個別に管理したりできます。たとえば、同じ DeliveryDestination を参照する複数の DeliverySource オブジェクトを作成することで、複数の Shield 保護からのログを同じ S3 バケットに送信できます。 Shield Advanced 攻撃フローログは CloudWatch Logs 配信インフラストラクチャを使用するため、他のベンドログと同様に、アカウントやリージョンをまたいで集約できます。 クロスアカウントポリシーを使用して一元管理された S3 バケット へ直接配信したり、 クロスアカウント・クロスリージョンの集約ルール を使用して CloudWatch Logs のロググループをレプリケートしたり、 クロスアカウントサブスクリプション を使用して共有 Firehose ストリームにストリーミングしたりできます。これらのオプションを活用して、マルチアカウント・マルチリージョン環境全体にわたる DDoS 攻撃トラフィックの統合ビューを構築することができます。 ステップ 1: 送信先リソースを作成する 送信先を選択します。 オプション A – S3 バケット : 長期保存と Athena クエリに最適です。 S3 バケットの作成 を参照してください。 オプション B – CloudWatch Logs ロググループ : リアルタイムモニタリングと CloudWatch Logs Insights に最適です。 CloudWatch Logs でのロググループの作成 を参照してください。 オプション C – Data Firehose 配信ストリーム : サードパーティツールや SIEM へのストリーミングに最適です。 Firehose ストリームの作成 を参照してください。 ステップ 2: 送信先リソースポリシーを設定する (必要な場合) 送信先リソースには、CloudWatch Logs 配信サービスに書き込み権限を付与するポリシーが必要です。ポリシーは送信先のタイプによって異なります。詳細については、 Amazon S3 に送信されるログ 、 CloudWatch Logs に送信されるログ 、または Firehose に送信されるログ を参照してください。 Amazon S3 を送信先とする場合は、2 つのオプションがあります。 自動ポリシー作成: バケットに既存のリソースポリシーがなく、 s3:GetBucketPolicy および s3:PutBucketPolicy 権限を持っている場合、ステップ 6 で配信を作成する際に AWS が必要なポリシーを自動的に作成します。ステップ 3 に進んでかまいません。 手動ポリシー更新: ポリシーをカスタマイズする必要がある場合や、組織で事前承認済みのポリシーが必要な場合は、 Amazon S3 に送信されるログ の手順に従って手動でポリシーを作成してください。 ステップ 3: 保護 ARN を取得する Shield Advanced はグローバルサービスであり、管理には us-east-1 リージョンを使用します。次のコマンドを実行して、 Shield Advanced 保護の一覧を表示 します。 aws shield list-protections \ --region us-east-1 出力から、ログを記録したい保護の ProtectionArn の値をコピーします。 ステップ 4: 配信ソースを作成する 次のコマンドを実行して配信ソースを作成します。 <protection-arn> をステップ 3 の ProtectionArn の値に置き換えてください。 aws logs put-delivery-source \ --name my-shield-delivery-source \ --resource-arn <protection-arn> \ --log-type FLOW_LOGS \ --region us-east-1 --resource-arn には、保護対象のリソースそのものの ARN ではなく、Shield Advanced の保護オブジェクトの ARN を指定します。Shield Advanced は、リソースをラップする個別の保護オブジェクトを作成し、フローログはその保護レイヤーから生成されます (基盤となるリソースからではありません)。 ステップ 5: 配信先を作成する 次のコマンドを実行して配信先を作成します。 <resource-arn> をステップ 1 で作成した送信先リソースの ARN に置き換えてください。 aws logs put-delivery-destination \ --name my-shield-delivery-destination \ --output-format plain \ --delivery-destination-configuration '{"destinationResourceArn":"<resource-arn>"}' \ --region us-east-1 --delivery-destination-configuration パラメーターは、 destinationResourceArn キーを持つ JSON オブジェクトを指定します。 その値には、S3 バケット、ロググループ、または Firehose ストリームの ARN を設定します。 出力結果から、トップレベル (レスポンス直下) の ARN フィールドの値をコピーしてください。これは配信先 ARN (バケット ARN とは異なります) です。この値はステップ 6 で使用します。 ステップ 6: 配信を作成する 次のコマンドを実行して、配信ソースと配信先を接続します。 <delivery-destination-arn> をステップ 5 の配信先 ARN に置き換えてください。 aws logs create-delivery \ --delivery-source-name my-shield-delivery-source \ --delivery-destination-arn <delivery-destination-arn> \ --region us-east-1 ステップ 7: 配信を検証する 次のコマンドを実行して、配信が有効であることを確認します。 aws logs describe-deliveries \ --region us-east-1 配信が有効になると、Shield Advanced は DDoS イベント中にフローログレコードを送信先に転送します。 クリーンアップ 継続的な料金が発生しないように、作成したリソースを削除します。 配信を削除します。 aws logs delete-delivery \ --id <delivery-id> \ --region us-east-1 配信ソースを削除します。 aws logs delete-delivery-source \ --name my-shield-delivery-source \ --region us-east-1 配信先を削除します。 aws logs delete-delivery-destination \ --name my-shield-delivery-destination \ --region us-east-1 (任意) コンプライアンスや分析のためにログを保持する必要がある場合は、フローログのデータをバックアップします。 送信先リソースを削除します。 警告: 送信先リソースを削除すると、すべてのフローログデータが完全に削除されます。 S3 バケットの場合: aws s3 rb s3://<bucket-name> \ --force \ --region <region> CloudWatch Logs のロググループの場合: aws logs delete-log-group \ --log-group-name <log-group-name> \ --region <region> Firehose ストリームの場合: aws firehose delete-delivery-stream \ --delivery-stream-name <stream-name> \ --region <region> まとめ Shield Advanced の攻撃フローログは、DDoS 攻撃を効果的に理解し対応するために必要な可視性を提供します。既存のオブザーバビリティ基盤と統合できるため、新しいツールの導入や複雑なセットアップを必要とせず、すぐに活用できるインサイトを得ることができます。今すぐ Shield Advanced の保護でフローログを有効にして、攻撃パターンへの即時の可視性を確保し、DDoS 防御態勢を強化しましょう。 次のステップ Amazon S3 内のログをクエリするための Athena テーブルの構築 Amazon CloudWatch Logs でのログデータの対話的な検索と分析 攻撃パターンに対する CloudWatch アラームの作成 フローログ設定に関する完全なリファレンスについては、 AWS Shield Advanced のドキュメント を参照してください。 Ken Kitts Ken は、Amazon Web Services (AWS) のテクニカルアカウントマネージャーであり、フィンテック分野におけるソフトウェア定義ネットワーキング (SDN) を含む、20 年以上のコンピューターネットワーキングの経験を持っています。仕事以外では、遺跡や博物館を巡ることが好きな旅行愛好家で、メキシコのテオティワカンがお気に入りの場所です。 翻訳は Solutions Architect の 長谷川 純也 が担当しました。
本記事は 2026 年 5 月 5 日 に公開された「 Amazon Aurora DSQL for global-scale financial transactions 」を翻訳したものです。 Amazon Aurora DSQL を使えば、強い整合性と低レイテンシーを両立しながら、複数の AWS リージョンにまたがるグローバル規模の金融トランザクションを実行できます。従来はこの選択にコストが伴いました。夜間のリコンシリエーションバッチ、手動フェイルオーバー手順、顧客残高や決済を扱うシステムでの短時間のデータ不整合リスクなどです。Amazon Aurora DSQL はグローバルに整合性のある強い耐久性を持つトランザクションを、アクティブ-アクティブの可用性とサーバーレス運用で提供し、従来のトレードオフを解消します。 本記事ではまず、分散整合性に対する従来のアプローチが金融ワークロードで不十分な理由を検証します。次に Amazon Aurora DSQL のアーキテクチャが分散整合性の課題にどう対処するかを説明し、3 つの本番ユースケース (勘定系、グローバル支出管理、デジタル通貨インフラストラクチャ) に適用します。最後に実装上の考慮事項と、 Amazon Aurora DSQL 無料利用枠 での始め方を紹介します。 金融サービスデータベースに求められる要件の変化 金融データベースには常に整合性と可用性が求められてきました。変わったのは運用環境です。10 年前、トランザクション処理のほとんどはリージョナルでした。銀行の中央台帳は 1 つのデータセンターで稼働し、トレーディングシステムは単一の取引所に対応し、日次バッチによる突合処理は当たり前のものとして受け入れられていました。現在、顧客は地理的に分散した拠点間でのリアルタイムな可視性を求め、規制当局は取引報告の期限を厳格化し、マルチリージョンでの可用性はもはや付加価値ではなく競争上の必須要件となっています。 よくあるシナリオで課題を説明します。あるリージョンの口座から引き落とし、別のリージョンの口座に入金する処理を、単一のトランザクションで実行する必要があります。従来の解決策は 2 フェーズコミット (2PC) で、コーディネーターノードが各参加者から合意を集めてからコミットします。動作はしますが、コーディネーターが単一障害点となり、ラウンドトリップ全体にわたってロックを保持し、部分的な障害にはテストが困難で運用コストの高いリカバリロジックが必要です。リージョン間ではコーディネーターのラウンドトリップに数百ミリ秒が加わり、クロスリージョントランザクション中のロック競合が最も重要なタイミングでスループットを制限する可能性があります。 多くのチームが代替手段として選ぶのは、非同期レプリケーションによる結果整合性、競合解決を伴うマルチプライマリ構成、あるいは専用の分散データストアです。これにより 2PC の調整負荷は回避できますが、その負担はアプリケーション開発者にのしかかります。共有状態を扱うサービスすべてに冪等性、競合解決、突合ロジックを実装しなければなりません。一時的な不整合を許容し、それを運用リスクモデルに織り込むチームもあります。分析やキャッシュのワークロードでは合理的なトレードオフですが、顧客残高、決済、取引を直接扱う場合には正当化が難しくなります。 Amazon Aurora DSQL はこの 2 つのアプローチの間を埋めます。2PC の調整負荷なしに強い整合性を提供し、結果整合性の突合負債も発生しません。 Amazon Aurora DSQL のアーキテクチャと金融サービスへの意義 Amazon Aurora ストレージエンジンの利点を、AWS リージョン間の分散運用向けに拡張した形で利用できます。 Amazon Aurora DSQL の紹介 でアーキテクチャの詳細を解説しています。ここでは金融サービスワークロードで最も重要な特性に焦点を当てます。 アクティブ-アクティブのマルチリージョン設計です。クラスターをデプロイした全リージョンで読み書きが可能です。各リージョンのノードは対等なピアとしてトランザクションを受け付け、書き込みトランザクションはリージョン間およびウィットネスリージョンに同期レプリケートされます。 ウィットネスリージョン は、軽量かつ中立的な第三の拠点で、コミットの判定に参加することで 3 拠点間のクォーラム(多数決)を維持し、トランザクションの永続性を確認します。クォーラムには 3 つの参加者のうち少なくとも 2 つの合意が必要なため、3 リージョンが必要です。2 つのアクティブリージョンのうち 1 つが停止しても、残りのアクティブリージョンとウィットネスリージョンで過半数を構成できるため、中断やデータ損失なくトランザクションのコミットが継続されます。もしウィットネスなしの 2 リージョン構成だったら、1 リージョンが失われた時点で、処理中のトランザクションがコミットされたのかどうかすら確認できなくなります。 マルチリージョンクラスターにより、データベースレイヤーで最大 99.999% の可用性を実現します。マルチリージョン運用を必要とするレジリエンス戦略において、手動フェイルオーバー、プライマリ/セカンダリの調整、フェイルオーバー後のデータ突合の構築・維持が不要になります。これは、各リージョンで独立して動作するアクティブ-アクティブのアプリケーション層と組み合わせると最も効果的で、スタック全体がすべてのレイヤーで集中的な調整なしにリージョン障害を吸収できるようになります。 サーバーレスで運用・スケーリング。キャパシティプランニング、レプリカ管理、シャーディング戦略の設計は不要です。コンピュート、コミット、ストレージの各レイヤーが独立して自動的にスケールします。Amazon Aurora DSQL は消費したコンピュートと I/O に対して課金されます。マーケットオープンや四半期末のスパイク時に使用した分だけ支払い、閑散期のアイドルには課金されません。予測困難な需要パターンを持つ金融ワークロードでは、従来のプロビジョニング型データベースアーキテクチャと比較して大幅なコスト削減が見込めます。 整合性モデル。トランザクションは最寄りのリージョンでローカルに実行され、Amazon Aurora DSQL は変更を伴うトランザクションのコミット時にのみリージョン間で調整します。整合性モデルはスナップショット分離を伴う楽観的同時実行制御 (OCC) で、トランザクション実行中にロックを保持しません。読み取り専用トランザクションはローカルのレイテンシーで完了し、リージョン間調整なしに一貫性のあるスナップショットを参照できます。書き込みトランザクションはコミット時にのみクロスリージョン調整コストが発生するため、調整ウィンドウは最小限に抑えています。 代わりに、各トランザクションはデータの一貫したスナップショットに対して動作し、Amazon Aurora DSQL はコミット時にのみ競合をチェックします。2 つのトランザクションが同じ行を変更した場合、一方が正常にコミットされ、もう一方はシリアライゼーションエラーとなり、アプリケーション側でリトライします。 この特性は以降のユースケースで重要です。通常は異なる行 (異なる口座、異なる取引) に触れるワークロードでは、競合は最小限です。同じ行を頻繁に更新するワークロードでは、カウンターをインプレースで更新するのではなく新しい行を追加するなど、行レベルの競合を減らすスキーマ設計が有効です。 Amazon Aurora DSQL のドキュメント で OCC 向けスキーマパターンの詳細なガイダンスを提供しています。 PostgreSQL 互換性。PostgreSQL を使用しているチームは、既存の SQL 構文、ドライバー、クライアントライブラリを Amazon Aurora DSQL でそのまま使用できます。本記事の例では馴染みのある PostgreSQL パターンを使用しており、既存のリレーショナルスキーマを最小限の変更で移行できます。Amazon Aurora DSQL が現在サポートしていない PostgreSQL 機能については、 Amazon Aurora DSQL の使用に関する考慮事項 を参照してください。 金融サービスのユースケース 以下のユースケースに共通するテーマは、複雑なマルチデータベースアーキテクチャを単一のグローバルに整合性のあるデータレイヤーに置き換え、突合プロセスや手動フェイルオーバー手順を排除する点です。異なるのは具体的な運用コンテキストと規制上の要件です。 勘定系と台帳の整合性 勘定系アプリケーションは、顧客口座、残高、トランザクションの正確なリアルタイム台帳を管理します。地理的に分散して運用する大規模銀行は、従来はリージョンごとに別々の勘定系を運用するか、バッチ処理でデータを同期していました。 これには 2 つの問題があります。プライマリリージョンがダウンすると、トランザクション処理が停止するか、データ損失を伴うフェイルオーバーが発生します。通常運用時でも、あるリージョンでの残高クエリが別のリージョンで処理された最近のトランザクションを反映していない場合があります。規制当局と顧客は、リージョン間での継続的な可用性とリアルタイムの正確性を期待しています。 Amazon Aurora DSQL は、各支店やリージョンのアプリケーションがローカルエンドポイントに読み書きを行い、更新は全リージョンに自動伝播することで、この問題を解決します。米国東部 (オハイオ) で処理された入金は、米国西部 (オレゴン) から照会する窓口担当者にも即座に表示されます。あるリージョンが利用不能になっても、残りのリージョンはデータ損失も手動フェイルオーバーもなくトランザクション処理を継続します。データベースが単一のグローバルに整合性のある状態を提供するため、システム間の突合なしに全リージョンから規制報告を作成できます。 具体例として、2 つの口座間の資金移動を考えます。従来のマルチリージョンアーキテクチャでは、リージョナルデータベース間の部分的な障害に対処するために、Saga パターン、メッセージキュー、補償トランザクションが必要になる場合があります。Amazon Aurora DSQL では単一の ACID (原子性、整合性、分離性、耐久性) トランザクションに簡素化できます。 以下のスキーマは、Amazon Aurora DSQL の分散アーキテクチャ向けに最適化されたいくつかの設計選択を示しています。UUID 主キーはリージョン間でのシーケンシャル ID の調整負荷を回避します。CHECK 制約はアプリケーションコードではなくデータベースレベルでビジネスルールを適用します。TIMESTAMPTZ 列はどのリージョンがトランザクションを処理しても一貫したタイムスタンプを提供します。これらの例ではわかりやすさのためにリテラル値を使用しています。本番環境では SQL インジェクションを防ぐため、データベースドライバーを通じたパラメータ化クエリを必ず使用してください。アプリケーションコードで送金開始前に十分な残高があることを検証する必要があります。以下の SQL は Amazon Aurora DSQL playground でインタラクティブに実行できます。 -- Schema: simplified core banking ledger CREATE TABLE accounts ( account_id UUID PRIMARY KEY, customer_id UUID NOT NULL, balance NUMERIC(18,2) NOT NULL CHECK (balance >= 0), currency VARCHAR(3) NOT NULL, updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE transactions ( transaction_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), from_account UUID NOT NULL, to_account UUID NOT NULL, amount NUMERIC(18,2) NOT NULL, description TEXT, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Funds transfer as a single ACID transaction BEGIN; UPDATE accounts SET balance = balance - 500.00, updated_at = NOW() WHERE account_id = 'acct-1234' AND balance >= 500.00; UPDATE accounts SET balance = balance + 500.00, updated_at = NOW() WHERE account_id = 'acct-5678'; INSERT INTO transactions (from_account, to_account, amount, description) VALUES ('acct-1234', 'acct-5678', 500.00, 'Funds transfer'); COMMIT; 口座の更新と取引き録は、アプリケーションがどのリージョンに接続していても原子的にコミットされます。送金元の残高が不足している場合、CHECK 制約で弾かれトランザクション全体がロールバックされます。片方の口座だけが引き落とされ、もう片方に入金されていない、そんな中間状態は起こりません。Saga オーケストレーション、補償トランザクション、夜間の突合バッチは不要です。 振替は通常、異なる口座行を操作するので、異なる口座に対する並行トランザクションは Amazon Aurora DSQL の楽観的同時実行モデルで競合なくコミットされます。まれに 2 つのトランザクションが同時に同じ口座を対象とするケースでは、OCC がコミット時に競合を検出し、一方のトランザクションがリトライされます。アプリケーション側でロックを取る必要はなく、整合性は保たれます。 グローバル支出管理と法人カードシステム 現代の支出管理サービスは、世界中の数千の企業のあらゆる金融取引を承認・追跡する集中的な意思決定レイヤーとして機能します。カードの利用、ACH (Automated Clearing House) 送金、電信送金、経費精算のいずれも、残高、与信限度額、加盟店管理、リスクスコア、会計マッピングに対する複数のトランザクション更新を発生させます。これらの操作は異なるロケーションから数秒以内に発生することが多く、わずかな不整合 (例: 承認判定に対して残高更新が遅れる) でも取引の拒否、過剰支出、不正リスクの露出につながります。 Amazon Aurora DSQL を使えば、リージョン間で単一のグローバルに整合性のある台帳を維持できます。各リージョンがローカルで書き込みを受け付け、同じグローバルに整合性のあるトランザクションセットの一部としてコミットします。これは、異なるリージョンにデプロイされた複数の決済プロセッサーや銀行パートナーと連携する場合に特に有用です。最大の価値は、統合された台帳と突合レイヤーにあり、リージョナルデータベース間のバッチ同期なしにグローバルに整合性のある残高ビュー、支出管理、会計記録を維持できます。 デジタル通貨インフラストラクチャ グローバルなデジタル通貨発行体は、複数のリージョン、ブロックチェーン、銀行パートナーにまたがる発行、償還、送金、決済をサポートする常時稼働サービスを運用しています。これらのサービスは、トークン供給量、顧客残高、取引状態を正確に追跡するリアルタイム台帳の維持が不可欠です。発行(ミント)、焼却(バーン)、送金イベントを取引所、決済プロセッサー、銀行パートナーの近くでローカルに処理でき、Amazon Aurora DSQL がそれらを原子的にコミットしてグローバルに可視化します。流通供給量、顧客残高、取引履歴はリージョン間で継続的に同期されます。 AWS 無料利用枠で始める 永続的な AWS 無料利用枠 と、分散データベース設計の専門知識がなくても開発を加速する AI スキルを利用できます。無料利用枠には毎月 100,000 Database Processing Units (DPU) と 1 GB のストレージが無料で含まれ、開発環境の運用や小規模アプリケーションのサポートに十分な容量です。 Amazon Aurora DSQL AI スキル は、分散ワークロード向けのスキーマ設計、外部キーなしの参照整合性、初日から本番対応のアプリケーション構築を支援します。Kiro や Claude Code などの AI コーディングツールと連携し、分散トランザクション向けに最適化されたスキーマ設計、レジリエントなマルチリージョンアプリケーションアーキテクチャの構築、既存の PostgreSQL ワークロードの Amazon Aurora DSQL への移行などのタスクについてインタラクティブなガイダンスを提供します。 Amazon Aurora DSQL スキルの全セットについては、 Amazon Aurora DSQL ステアリングガイド を参照してください。 まとめ 本記事では、Amazon Aurora DSQL がグローバルに分散した ACID トランザクション、最大 99.999% の稼働率を持つアクティブ-アクティブの可用性、サーバーレス運用を単一のマネージドサービスで実現する方法を紹介しました。2 フェーズコミットと結果整合性の限界にアーキテクチャがどう対処するかを説明し、金融サービスチームが構築する 3 つの本番パターン (原子的なクロスリージョン送金を行うコアバンキング台帳、グローバルに整合性のある経費管理システム、リージョン間で流通供給量と残高を同期するデジタル通貨プラットフォーム) に適用しました。 実際に試すには、 Amazon Aurora DSQL サービスページ から無料利用枠クラスターを作成し、 開発者ガイド で接続設定、クエリパターン、スキーマ設計を確認してください。アーキテクチャの詳細や機能比較については Amazon Aurora DSQL のドキュメント を参照し、移行のビジネスケース構築については AWS アカウントチームにご相談ください。 著者について Trevor Spires Trevor は、AWS の金融サービス担当シニアソリューションアーキテクトです。キャピタルマーケットおよびフィンテックのお客様と密接に連携し、コアインフラストラクチャと AI システムのクラウドでのスケーリングとセキュリティ確保を支援しています。 Raluca Constantin Raluca は、Amazon Aurora DSQL を専門とする AWS のシニアデータベースエンジニアです。Oracle、MySQL、PostgreSQL、クラウドネイティブソリューションにわたる 18 年のデータベース経験を持ち、データベースのスケーラビリティ、パフォーマンス、リアルタイムデータ処理に注力しています。 Jigna Gandhi Jigna は、AWS の金融サービス担当シニアソリューションアーキテクトです。フィンテック、Web3、銀行組織と密接に連携し、最新の金融プラットフォームを支えるスケーラブルでセキュアかつレジリエントなクラウドおよび AI ソリューションを設計しています。 Narendra Reddy Bathina Narendra は、AWS の金融サービス担当テクニカルアカウントマネージャーです。フィンテックのお客様と連携し、データベース、ストレージ、クラウドオペレーションの豊富な現場経験を活かして、本番システムのレジリエンス、パフォーマンス、スケーラビリティの向上を支援しています。 Viraj Padte Viraj は、AWS の金融サービス担当シニアソリューションアーキテクトです。さまざまなフィンテックのお客様と連携し、コアビジネスおよび AI を活用したプラットフォームとソリューションを支えるエンタープライズ対応のインフラストラクチャを設計しています。 この記事は Kiro が翻訳を担当し、Solutions Architect の Kenta Nagasue がレビューしました。
















