Ruby on RailsとGoの強みを活かした合理的なアーキテクチャ
こうした分析を経て、小林氏が出した結論は「お金を取り扱う部分はGoを採用」し、「お金以外を取り扱う部分(アプリのAPIサーバーや管理画面)はRuby on Railsを採用」するという、両方の言語を併用するアーキテクチャだった。
具体的には「偶有的複雑性」の領域をRuby on Railsが担い、口座開設時の本人確認やログイン時の認証、通知機能などを実装。豊富なライブラリにより、Webアプリケーションとしての一般的な機能開発に余計な工数を割く必要がなくなった。一方で「本質的複雑性」である、インターネットから隔離された証券取引領域の実装にはGoを採用し、証券システムのドメインに特化させた。
続けて小林氏はRuby on RailsとGoの特性を活かした、「偶有的複雑性」と「本質的複雑性」それぞれの実装についてより詳しく説明。
顧客の個人情報やマイナンバー、本人確認書類の画像データを預かるRuby on Railsの実装部分では、データベースの漏洩対策として厳格な暗号化が求められる。そこで、クラウドプロバイダーが提供するKey Management Service(KMS)を活用し、レコードごとに異なるデータ暗号鍵を動的に生成して暗号化を行うロジックをattr_encrypted gemを使って実装。小林氏は「データベースに暗号化されたフィールドが入っているけれども、プログラム上は生データとして扱えます」と、そのメリットを説明する。
一方、お金の計算と取引を担うGoの実装部分では「絶対的な整合性」が最優先される。システム間の連携においてネットワークの瞬断やリトライが発生しても二重発注が起きないよう、すべてのAPIは冪等性を担保するように設計。同一の顧客から同時に複数の注文リクエストや状態変更の要求が届いた場合、処理の開始時点でデータベース上の起点となるレコードの行ロック(Row Lock)を確実に取得し、シーケンシャルな排他処理を行うことでデータの不整合を排除している。しかし、これほど緻密に設計されたアーキテクチャであっても、実際の運用環境においては、さらに複数の外部システムと連携した整合性の維持が必要となる。
