こんにちは、エンジニアの富岡です。9月26日、27日に行われた Kaigi on Rails 2025 にウォンテッドリーからは5名のメンバーで参加してきました。参加した各メンバーから参加レポートを連続で公開します。
本記事では、私が聞いたセッションのうち印象に残ったものを、いくつかピックアップしてご紹介します。
5年間のFintech × Rails実践に学ぶ - 基本に忠実な運用で築く高信頼性システム
高い信頼性が求められる Fintech サービスにおいて、それを実現するために、どう運用上の工夫や取り組みをしているか、また運用を見据えて開発においてもどういった工夫をしているかという内容でした。
ときに面倒に感じてしまう地道な取り組みも、サービス開始の初期から手を抜かずに組織単位でコツコツと築き上げてこられたことがわかる内容となっており、SmartBank さんの開発組織の強さを感じました。
登壇者も話されていましたが、発表内で紹介された取り組みは Fintech サービスでなくても参考にできるものが多かったです。個人的には特に運用における取り組みが印象的でした。アラートを受け取ったときに実装の詳細を知らなくてもリトライ可否や手順を判断できるようにする「バッチ管理」のしくみや、手動オペレーションを形式知にし、累積所要時間をトラッキングする「Runbook」の取り組みについては、自社でも真似したいと思いました。
スライドの中に関連する記事や発表のリンクを入れてくださっていたのもありがたかったです。この発表を起点にそれらの内容も深ぼってみたいと感じました。
2重リクエスト完全攻略HANDBOOK
サブミットボタンの連打や、ネットワークエラー等によるクライアント側のリトライなどによって起きる「2重リクエスト問題」への対策法を幅広く紹介する内容でした。私自身も1年ほど前に、外部システムとのAPI連携で二重リクエスト対策を実装することがあり、そのときの自分の選択と照らし合わせながら面白く聞いていました。
発表の中では、クライアント側でできる対策として、
- サブミットボタンの制御
クライアント側とサーバー側で連携して行う対策として、
- Idempotency-Key ヘッダー
- ETag + If-Match
- ワンタイムトークン
サーバー側のみでできる対策として、
- Post-Redirect-Get パターン
- 排他制御
- テーブル設計
- レートリミット
- APIキャッシュ
といった手法が紹介されていました。
私自身は二重リクエスト排除を実装するときは、クライアント側に一意なキーを発行してもらい、それをテーブルのカラムに入れてユニーク制約で排除するか、Redis で存在チェックするか、といった発想がまず思い浮かびます(Idempotency-Key ヘッダーはこうした類型手法の標準化を試みる仕様ですね)。この方法は利用できるシーンの汎用性が高い一方で、クライアント側も正しく実装できていないと二重リクエストを防ぐことができません。例えば、クライアント側がネットワークエラーによるリトライ時にキーを再発行するような実装になってしまっていたら意味がありません。その点、APIキャッシュやワンタイムトークン、レートリミットといった手法は、それぞれで使えるシーンは限定されるものの、クライアント側の正確な実装によらずともサーバー側で信頼性の担保が可能である、というメリットがあることを学びました。
実例として挙げられていた、クレジットカードの発行のような、短期間に二度行われることはないだろうとビジネス上割り切れるものは、Idempotency-Key ヘッダーのような実装コストのかかるしくみではなく、あえて軽量なレートリミットで防いでしまうという発想もなるほどと感じました。
結局はどんなときでもこれを使っておけばいいというものはないので、状況に応じて適切な手法を選び取るの大事だと捉え、そのための引き出しが増えたという意味で勉強になりました。
「技術負債にならない・間違えない」権限管理の設計と実装
認可判定のロジックがコントローラーやフロントエンドのコードの中に書かれると、コードベース内で一貫性を保つことが難しくなったり、仕様を把握するのが難しくなったりします。こうした問題の解決策としては Rails では Pundit などの gem を使って、認可判定ロジックを一箇所に集約定義することが一般的です。
登壇者は Pundit を使った実装にも不満を持ち、さらに「間違えにくい」設計を志向していました。具体的には、Pundit のレールに従うと、あるリソースのポリシークラスの中でユーザーのロールに基づく判定とその他の条件に基づく判定とがごっちゃに書かれることになり、これにより認可判定の理解が難しくなるのではないかと着目していました。代わりにリソース x ロールごとにポリシークラスを定義したら、どのロールのユーザーがどういう条件で操作が許可されるかが一目瞭然になると考え、そのしくみを自作して自社のシステムで利用してみたという内容でした。
発想としてはデザインパターンにおける State パターンを認可処理に適用したような形で、たしかに見通しはよくなりそうだと思い、面白いと感じました。
この発表を聞きながら、自社のコードを反省することが多かったです。ウォンテッドリーでも Pundit gem を使っていますが、本来望ましいリソース単位でのポリシー定義から離れて、コントローラーや gRPC サービスと1対1でポリシー定義をしてしまっている箇所が多く、ドメイン上同一の認可判定ロジックが複数箇所に分散してしまっているという問題があります。また、権限ごとのボタンの表示・非表示といった認可ロジックがフロントエンド側に書かれてしまっている箇所も残念ながら多くあります。この発表を聞いて、改めて認可判定ロジックを一箇所に集約することの重要性を感じ、自社のコードも整理していきたいと感じました。
おわりに
私は今回 Kaigi on Rails にはじめて現地参加しましたが、やはり現地参加すると会場の活気に触れられるのがいいですね。たくさんの発表を聞いて刺激を受け、インプットしたいことや自社で試してみたいことに溢れた2日間でした。
すばらしいカンファレンスを主催してくださった運営への皆様に改めて感謝を申し上げます。