Griffin - Clojureで作られた完全規制APIベースの銀行
(juxt.pro)- フィンテックが口座開設・決済・オンボーディングを銀行APIのように直接組み込める banking-as-a-service プラットフォームであり、2023年3月に英国の銀行ライセンスを取得して規制銀行となった
- システムは Clojure on Kubernetes on AWS 上で動作し、ほとんどの入力をイベントに変換するイベントソーシング構造とFoundationDBストアを組み合わせている
- FoundationDB はトランザクションと同時書き込みをサポートする strict-serializable key-value store であり、GriffinはDatascriptを移植したDatomic類似レイヤーで原子的な読み書きを構成している
- ビジネスロジックは Clojure map を受け取り Clojure map を出力する小さな log processor を中心に分離し、外部システムアクセスはプロトコルと専用procに限定している
- Clojureの不変性と監査ログへの親和性が金融サービスの要件に合っており、リモート採用と組み合わせれば小さな候補母集団でも高品質なエンジニアを見つけやすいと見ている
APIとして提供される規制銀行プラットフォーム
- Griffin は、フィンテック企業が 銀行機能 を迅速かつ安全に統合できるよう支援する banking-as-a-service プラットフォームである
- 2023年3月にFinancial Conduct AuthorityからUK banking licenseを取得し、完全に規制された英国の銀行となった
- Griffinは自らを “the bank you can build on” と呼び、銀行のためのAWSのような基盤を目指している
- 顧客オンボーディングAPI
- 銀行口座作成API
- 決済API
- フィンテックがこうした機能を提供するには法的に銀行との提携が必要で、現在はメインフレームを使う既存の high street bank と協業するケースが多い
- Griffinは銀行ライセンスと技術プラットフォームをあわせて提供し、将来のフィンテックがその上にサービスを構築できる基盤になろうとしている
- ライセンスは取得したが、当時は mobilization 段階にあり、監査完了・追加資金調達・コード作成完了後にこの段階が終わる
- 目標時期はその年のQ3またはQ4だった
Clojureを選んだ背景
- Clojureは 不変性、表現力、監査ログが必要な金融サービスとの適合性を理由にプラットフォーム言語として選ばれた
- Allen Rohnerは2007年ごろにRich HickeyのClojure発表を見て、自分が作っていたLispより優れていると判断した
- 2011年にCircleCIを創業した後も長期間Clojureを使い、CircleCIでもうまく機能し、金融サービスにも合うと考えた
- JVMについては最初の数年間、その利点を十分に認識していなかったが、その後は大きな利点として評価が変わった
- 他の niche startup language はライブラリ不足やコンパイラ・ランタイム性能の問題に直面しうる
- JVMはこうしたリスクを減らす基盤になる
- 言語選択は会社の性格を表し、PythonやJavaよりClojureのほうが強い選択だと判断した
- niche language を使うと候補者数は減っても 上級人材の比率 は高まる可能性があると見ている
FoundationDBで構築したデータレイヤー
- Griffinのアーキテクチャは Clojure、Kubernetes、AWS上で動作し、ほぼ全面的にイベントソーシングで構成されている
- データベースには FoundationDB を使用している
- FoundationDBはトランザクションをサポートする strict-serializable key-value store である
- シリコンバレーのスタートアップとして始まった
- 2015年にAppleに買収された
- 2018年ごろにAppleが再びオープンソースとして公開した
- AppleはiCloud本番環境で使用している
- AppleはFoundationDBが毎秒約100万トランザクションで動作するベンチマークを実施している
- strict serializable はデータベース整合性における 最も高い水準 に当たる
- 基本APIは
get a key、set a keyに近く、SQLではない - GriffinはDatascriptをFoundationDBに移植して Datomic類似レイヤー を構築している
- strict-serializable なデータストア上で原子的なクエリが可能である
- トランザクションベースの読み取りと書き込みをサポートする
- FoundationDBは single writer ではなく concurrent writes をサポートする
- Griffinは毎秒1,000件を超えるトランザクションが必要であり、その要件を満たしている
イベントソーシングとlog processor
- Griffinシステムのすべての入力はイベントになる
- API request
- サードパーティ webhook
- イベントはmessage logに入り、Griffinではイベントは
typeフィールドと key/value、spec を持つ Clojure map である - システム全体はイベントへの反応として構成されている
- 小さな log processor を
procと呼ぶ- proc は「message type Aを受け取り、反応としてBまたはCをemitする」という形で動作する
- 各procは独自の private state を持つ
- メッセージフローはグラフとして構成でき、イベントは terminal node に到達するまで移動する
- たとえばWebサーバーはHTTPイベントを受け取り、決済リクエストを記録したあと、
payment createdまたはpayment rejectedイベントを待ってからクライアントに応答する- このフローはNetty asynchronous HTTP handlerを使う
- すべてのイベントはFoundationDBに記録される
- 各 log processor はFoundationDB内に、自身の namespace のような private data を持つ
- proc は特定のイベントタイプが記録されるのを監視し、自身のイベントをFoundationDBに再度記録する
- FoundationDBはDB key変更の監視機能を提供し、reactive system を効率的に作れる
- データベースと別のメッセージングシステムを併用すると race condition の可能性が生じる
- たとえば1つのメッセージはディスクへ、もう1つはネットワークへ送られる状況で、観測者が両者を異なる順序で見ることがある
- Griffinは単一経路に単純化するため、FoundationDBに記録する方式を使っている
モノレポとビジネスロジックの分離
- Griffinは monorepo を使っている
- 現在は効率のため、多くの log process が同じJVM上で動作している
- それぞれは独立しており、別個のJVM process として実行することもできる
- 現在は数百弱規模のprocを単一JVMで動かしている
- ビジネスロジックはできるだけ単純でクリーンに保っている
- 個々の log processor namespace はほぼすべて pure Clojure である
- サードパーティライブラリはほとんどない
- side effect も非常に少ない
- log processor は Clojure map を入力に受け取り、1つ以上の Clojure map を返す関数に近い
- proc state には protocol があり、相手側の実装を知らなくてよい
- テスト時には in-memory database として使える
- 実運用時にはFoundationDBに書き込める
- 外部世界とのインターフェースは可能な限り小さく保っている
- ほとんどのprocは、自分の内部状態に書き込み、メッセージをemitすることしかできない
- ネットワーク呼び出し不可
- AWS呼び出し不可
- その他の外部動作なし
- 外部システムと通信する必要がある場合は、専用の dispatch handler を持つ特別なprocを置く
- AWSと通信するproc
- clearing bank と通信するproc
- 他のAPIと通信するproc
利用しているClojureエコシステム
- ビジネスロジック内部ではライブラリをほとんど使っていない
- API web server や service gateway のように外部世界と接する領域では次を使っている
ringnettyreitit
- Clojure spec を広範に使用している
- AWS連携にはCognitect
aws-apiライブラリを使っている - アプリケーション構成とリソース管理には closeable のブログ記事に基づく方式を使っている
- ComponentやIntegrantなしで
with-openで十分というアプローチである - lexical scope を得られ、binding宣言順が構成順を強制する
Closeableを実装しない状態オブジェクトや stateless object をwith-openブロックで宣言するための小さな helper を使う
- ComponentやIntegrantなしで
採用とチーム構成
- GriffinはClojure採用について、候補者数は少ないが良い候補者の比率は高いと見ている
- Java採用ではCVが1,000通来ても良い候補者が10人かもしれない
- Clojure採用ではCVが13通でも良い候補者が10人かもしれない、という表現をしている
- 小さな採用母集団では リモートワーク が重要である
- 地理的制約を減らせば、世界全体、3つのタイムゾーン内、欧州全体など、より大きな母集団を作れる
- 短期間でエンジニア100人を採用しなければならない状況は anti-pattern だと見ている
- 会社全体の人数は約70人である
- Engineeringは約22〜24人である
- 約3分の2はUK
- 約3分の1はEU
- ドイツ4人、スウェーデン4人、アイルランド1人ほど
- 本社はロンドンだが、開発者のほとんどはロンドン以外のUKにいる
銀行レベルの運用レジリエンス試験
- Griffinは銀行として operationally resilient でなければならず、これはダウンタイムがあってはならないという要求に近いと見ている
- 金を扱うため、問題が起きても顧客の資金を失わないことを実際に証明しなければならない
- 関心を持っているテストの方向性はFoundationDBチームの方式に近い
- FoundationDBチームはデータベースシミュレータを構築している
- 約20種類の process type、つまりクラスタ内部の役割を single-threaded C++ アプリとして書いている
- C++上に actor-model concurrency compiler を構築している
- すべての system call と network call を protocol 経由で実行し、障害を注入できるようにしている
- multi-threading も message sending ベースの actor model を通じて処理している
- この環境では決定論的に障害を注入できる
- メッセージAとBを送ったが、相手にはB、Aの順で届く場合
- メッセージ処理中にディスク書き込みエラーが発生する場合
- これは
test.checkの generative testing に似ており、システムのあらゆる非決定性を制御可能な単一の乱数からseedする方式と見なせる - 制御したい対象は disk errors、network errors、message reordering である
- 現在の問題は、Java threading libraries、NIO、disk write の動作を制御する方法がない点である
- Jepsenと精神は共有しているが違いもある
- Jepsenは複数VMを使いプロセスを落とすような brute force に近いと見ている
- データベース状態を内部から検査しにくく、カバレッジを把握しづらい
- 完全に制御可能な環境では system call やメッセージ interleaving を列挙でき、in-memory なので非常に高速に確認できる
- FoundationDBチームはこのようなテスト環境を初期に作っており、これはFoundationDBへの信頼につながる要素になっている
- Griffinは採用中であり、Griffin careers page で情報を確認できる
1件のコメント
Hacker News の意見
Griffin の現 VP of Engineering である James Trunk は、私が見た中で最も明快で面白い Clojure 技術入門の発表をしていた。おすすめ。
https://youtu.be/C-kF25fWTO8?si=PnjMNLdBLJ8zqSu-
今の問題は、基盤となる Java のスレッディングライブラリ、NIO、ディスク書き込みの挙動を制御する方法がないことで、そうしたシステムの性質上、今後も不可能だと思う。
非決定的なリクエスト順序やジョブスケジューリングを使うシステムでは、決定的実行は得られない。複数の OS スレッドを常に使ったり、テストで別プロセスを複数立ち上げたりするとそうなる。
無理やり決定的にすることはできるかもしれないが、アプリケーションの状態機械におけるすべての遷移に、テストが制御できる同期ポイントを埋め込む必要があり、非常に難しい。
実務的には、システムの中核を完全に同期的に設計し、実行時により高い層で並行性を追加する方法しかなさそうだ。
procsは Clojure プロトコル(Java インターフェース)の向こう側で起きることを除けば副作用がない。そのため、テスト中はすべての副作用をスタブに置き換えられる。私たちの「ユーザー」コードはスレッディングライブラリにアクセスできず、スレッディングは「カーネル」コードで起きる。
実際に、すでにこの方式が実装されている良い例は https://www.youtube.com/watch?v=4fFDFbi3toc で見られる。
すでに missionary 自身のテストのために missionary のフローを計測し、状態遷移を検証している。
2人の創業者が一緒に Learning ClojureScript という本を書いているのはなかなかすごい。
https://www.packtpub.com/product/learning-clojurescript/9781...
「私たちは銀行免許を持つテクノロジー企業だと冗談を言うことがあります」という一文は、物事がうまくいかなかった場合、後になってかなり印象の悪い引用になり得る。
私の雇用主は、自社をソフトウェアで研究成果を商業化する教育研究会社と呼んでいて、私にはそのほうがはるかに納得できたし、文化もより良くしていた。
銀行業でそうした知識を学び直すコストは非常に高くつく可能性がある。
真面目な質問だし、乱暴な言い方は申し訳ないが、自分が使うサービスがどの言語で書かれているかをなぜ気にする必要があるのか? Clojure で書かれていることがなぜ重要なのか? 仕事では Clojure 開発者なので、こういうものが Clojure で書かれているのを見るのは素晴らしいが、なぜ自分がそれを気にすべきなのか分からない。
これはコミュニティで私が本当に嫌いな点の一つだ。Clojure は強力な言語で、私も楽しく使っているが、コミュニティには、あるプロジェクトでこの言語を使っていることを他人に伝えて正当化しなければならないというインポスター症候群のようなものがある感じがして奇妙だ。
要点がよく分からない。これが文明社会で不適切な行為にでもなるのだろうか?
かなり無知に聞こえる。「興味がない」なら、わざわざ関わらなくてもいいし、書き手が書きたいことを書けるようにしておけばいい。
90年代に PHP や Python の開発者たちが「なぜ Microsoft ASP を使わないのか」といったビジネス上の質問に答えるため、こうした事例を共有していたのを覚えている。
あるいは、自社に来る開発者を惹きつけようとしているのかもしれない。
こういうAPI銀行はなぜいつも英国にあるのか? 何年も前から curlで銀行業務をしたいと思っていたのに、米国では誰も提供していない
一方、英国は新しい銀行や新しい技術を積極的に奨励してきた。個人口座間の即時無料送金はほぼ20年前からあり、非接触決済は少なくとも10年、モバイルバンキングは数十年、政府が義務化した銀行APIはほぼ5年になる
要するに英国には、銀行の基準では速いペースで革新してきた非常に活発な銀行セクターがあり、さらに速いイノベーションのための環境とエコシステムがよく発達している
米国では、銀行が何十年も前に技術革新を諦め、手数料や顧客への懲罰的な扱いで革新するほうを好んだように見える。そのため新たなイノベーション環境がなく、既存の銀行にとっては競争するより競合を押しつぶすほうがずっと簡単なのだ
英国も最近までは独立系銀行の数が驚くほど少なかったのに、なぜ同じことが起きなかったのかは、顧客の権利を多く保障し、それを守らない銀行を積極的に罰する法律と規制の性質による可能性が高い
米国でAPIを持つ銀行は大手フィンテックとの提携に注力する傾向があり、単純なAPIでも一般的な銀行口座に比べて高くつくだろう。例えば米国のGrasshopper Bankは、通常の商業銀行口座の上にAPIを提供する数少ない銀行の一つだ
私はAPIを提供する複数の米国銀行をサポートしているTreasury Primeで働いている
個人口座の分野では、MonzoとStarlingがいわゆるチャレンジャーバンクの中で最もよく知られている[1]
[1]: https://en.wikipedia.org/wiki/Challenger_bank
Column – 開発者向けの認可銀行
https://news.ycombinator.com/item?id=31109170
「オープンソース化すべき追加の独自技術がもう一つある。DatascriptをFoundationDBに移植した」というのは、ぜひ公開してほしい
Datomic代替としてどのように動くのか気になる
「法的には、フィンテックがこうしたことを行うには銀行と協力しなければならず、今はそれがメインフレームを使う伝統的な大手銀行を意味する。Griffinは、未来のすべてのフィンテックが基盤とする銀行であり技術プラットフォームだ」という文は、2016年に書かれたのかと思う
市場はすでに動いている。Griffinは良さそうだが、多くのところより数年遅れていて、ClearBankのような確立した事業者がすでに銀行APIをうまく提供している
もっと多くの事業者が参入する余地はあるのでGriffinの市場参入は歓迎だが、ピッチがここまで弱くなければよかった
そして良いAPIだけでは不十分だ。顧客層に合った運用モデル全体が必要で、それを構築するほうがはるかに難しい
まだではない。「監査を完了し、さらに資金を調達し、コードを書き終えたら補助輪を外す。今年の第3四半期か第4四半期ごろになるだろう」とある
文章が「スタートアップでは使える最も強力な言語を使うべきで、それがClojureだ」で始まると本当に嫌になる
それは単にあなたの見解にすぎない。スタートアップでは、チームがMVPを最速で作ってリリースし、最初の顧客や投資を得られる言語を使うべきだ。一般的なスタートアップならローコードやノーコードのプラットフォームかもしれない。フィンテックではその可能性は低いだろうが
あえて言えば、LLMと機械学習のおかげでPythonが最も強力な言語だとも言えるし、私は普段PHP開発者だ。Pythonは、Pythonを36000倍速くするとされるMojoのおかげでさらに強力になるかもしれない
だが、ある言語Xがスタートアップで使うべき唯一かつ最も強力な言語だとは絶対に言わない。それは完全な嘘であり、単なる見解だ
例えば私の見解では、その見解に同意する :-) 私の一人創業の事業はClojureとClojureScriptなしには不可能だっただろうし、これはこの言語の「力」を示している
一人の開発者が複雑なアプリを何年にもわたって書き、保守できるようにしてくれるので、私はこの言語を「強力」だと考えている。私に力を与えてくれる
Clojureには、PythonやPHPのようなより大衆的な言語よりも、他のLispと重なる部分が多い、かなり内向きのコミュニティがある。だからClojureが最も強力な言語というクリシェは、ある程度事実ではあるものの、使っていない人には驚きに聞こえるかもしれない
私たちClojure開発者はすでに慣れていて、今では優位性を前提に話すのがほとんど挨拶のようになっている
LLMの出力を扱うのにもClojureのほうが好みだ。もちろんPythonがぴったり合うところでは今でもPythonを使う