SupabaseからClerkを経てBetter Authへ
(blog.val.town)- Val Townは2023年にSupabaseを離れ、データベースはRender、認証はClerkへ移行したが、ユーザー・セッションの責務を外部化する構造が合わず、1か月前にBetter Authへ移行した
- Clerkはユーザーテーブルをなくす方向を提案したが、Val Townはソーシャル機能のため複数ユーザーのコンテンツ、ユーザー名、アバターを頻繁に表示する必要があり、Clerk APIの制限と同期のため実質的にユーザーテーブルを2つ運用する複雑さが生じた
- Clerkがセッション更新まで担うことで単一障害点となり、Clerk障害時にはログイン・ログアウトだけでなく、すでにログイン済みのユーザーもサイト全体を使いにくくなり、2025年5月以降のステータスページ基準の稼働率は99%から99.9%の間と感じていた
- Val TownはClerkのSDK、管理機能、不正利用対策、ダッシュボードを有用と見ていたため即座に書き直しはしなかったが、サードパーティのセッション管理を再び信頼しないという基準を立てた
- Better Authはコード品質、フレームワーク統合、独立したオープンソースの中核が要件に合っており、Val Townは約2週間にわたりClerkとBetter Authを同時にサポートし、2種類のCookieを受け付けて段階的にセッション移行を進めた
移行の背景
- Val Townは2023年にSupabaseから離れ、より伝統的なデータベース構成へ移行する中で、データベースはRender、認証はClerkに置き換えた
- 2023年末にはClerkから離れるべきだというIssueが登録され、1か月前にBetter Authへ移行したことでそのIssueは閉じられた
- ClerkとSupabaseはそれぞれ5,000万ドルの資金調達、評価額50億ドルで1億ドルを調達した成功サービスだが、Val Townの構成はClerkの想定と大きく衝突していた
- 移行プロセスでは多くの回避策、バグ、障害があり、特にClerkがユーザーテーブルとセッションテーブルの両方を代替しようとする構造が中核的な問題として明らかになった
中核的な問題: ユーザーテーブルとセッションテーブルの外部化
-
Clerkをユーザーテーブルとして使いにくかった理由
- Clerkは2021年の“Consider dropping your users table”記事や、2023年の“DELETE your Users table”動画のように、ユーザーテーブルをなくす方向を強く提案していた
- Val Townは初期移行時、ユーザー設定、アバターURL、メールアドレスのようなデータは必要なときにClerk APIから取得できると見ていた
- Clerk SDKの
rootAuthLoaderには、アプリケーション全体の認証を処理しつつユーザーデータを要求するloadUserオプションがあり、開発環境ではうまく動作した - 本番環境ではそのエンドポイントの制限がアカウント全体・全ユーザー合算で1秒あたり5リクエストであり、この問題は後にオプション削除で解決された
- Val Townのようにソーシャル機能のあるサービスでは、多くのページで他ユーザーのコンテンツ、ユーザー名、アバターを表示する必要があるため、ユーザーが自分のアバターや設定だけをJWTから読むというClerkの標準UI前提とは合っていなかった
- Clerk側の助言は、アバターやその他の情報をClerkとVal Townのユーザーテーブル間で同期することだったが、その結果、同じ情報の正本が2か所に分かれ、ユーザーテーブルを2つ運用する複雑さが生まれた
-
Webhook同期が生んだ登録フローの複雑さ
- ClerkのデータをVal Townのデータベースへ同期するにはWebhookを使う必要があり、登録プロセスは複雑で扱いづらくなった
- 登録直後の短い間、ユーザーはClerkアカウントはあるがVal Townのデータベース行はない状態になりえた
- Val Townではユーザー名が必須のため、ユーザーがClerkアカウントとデータベース行は持っていても、アカウントがまだ完成していない状態にもなりえた
- ユーザー設定は、認証方式のようにClerkが管理する項目と、ユーザー名やエディタ設定のようにVal Town側で必要な項目に分ける必要があった
Clerkが単一障害点になったセッション構造
- Cookieベースのユーザーセッションは通常、短く保たれ継続的に更新される。そうすることで素早く無効化できる
- この構造では数分ごとにユーザーがセッションCookieを新しいCookieへ交換する必要があり、Val TownのサブドメインがClerkへリクエストを送って更新を処理していた
- Val Townはセッションテーブルを持たず、セッションに対する責務も負っていなかった
- この方式は認証の責務を避けたい場合にはよいが、Clerkが停止するとログインとログアウトだけでなく、すでにログイン済みのユーザーにとってもサイト全体が使えなくなる
- Clerkは頻繁に、しかも長時間の障害があり、2025年5月以降のステータスページ基準では稼働率は99%から99.9%の間だと感じていた
- 複雑なシステムの信頼性は、重要コンポーネントの結合信頼性のうち最小値に縛られる
- この2つの大きな問題に加えて、Clerkに関する他のバグや問題もあり、その大半は最終的に修正されたが、自動でIssueを閉じる“Stale Issue Bot”とも格闘する必要があった
すぐに移行できなかった理由
- 「XからYへ移行する」作業は開発速度とチームの精神的安定を損ねうるため、Val Townは本当に必要な場合でなければ書き直しを避けたかった
- ClerkはRemix、Fastify、Expressなど、Val Townが使っていた技術向けのSDKを提供しており、それらフレームワークの変化にもかなりよく追随していた
- Clerkの管理機能と不正利用防止機能は、カスタマーサポート上の問題解決や不正ユーザーの抑止に役立った
- Clerkが特に適していたのは、ソーシャル要素がなく、ユーザーテーブルを必要としない比較的シンプルなフロントエンド中心アプリだった
- 始めやすく、価格も受け入れ可能で、Clerkのダッシュボードもかなり良かった
- 認証の代替手段は多くなく、オープンソースの認証ソリューションには古く、事実上放置されたものも多かった
- Auth as a Serviceのプラットフォームにはベンダーリスクがあり、Clerkと同じ問題が繰り返される可能性もあった
- Val Townは認証をゼロから自作して新しくて気まずい脆弱性にさらされたくはなかったが、同時にベンダーへ責務を渡しすぎたくもなかった
- 特に、サードパーティのセッション管理を再び信頼しないという基準が生まれた
Better Authの選定と移行方法
- Better Authは、高いコード品質、複数フレームワークとの良好な統合、独立したオープンソースプロジェクトとして実運用可能である点で、多くの条件を満たしていた
- Better Authも大半は1社によって開発される大規模で複雑なコードベースであり、ベンダーリスクは残っている
- ただし、セッションとユーザー認証を動かすために第三者が継続的にオンラインである必要はなくなった
- WorkOSのAuthKitも有力候補で非常にスムーズだったが、2つのベンダーを経たあとでは、独立して動作し中核がオープンソースである代替手段が重要になった
- Better Authのダッシュボードと有料アドオンもVal Townの要件に合っていた
- Val Townはすべてのデータを自ら管理し、プラグインがVal Townサイト上でAPIを提供して、Better Authダッシュボードが情報取得と軽量なユーザー管理を行えるようにした
- Better Authの有料サービス“Infrastructure”は、Val Townの使い方では事実上ほぼステートレスで、セッション管理には関与しない
- 移行期間中、Val Townは約2週間にわたりBetter AuthとClerkを同時にサポートした
- 認証を処理するすべてのエンドポイントが2種類のCookieの両方を受け入れ、ログインページがBetter Authセッションを提供することで、ユーザーは段階的にBetter Authへ移行した
- セキュリティに関わる作業である以上、すべてのコードを綿密に読み、書き直し、テストする必要があり、最終的な純粋なBetter Auth認証コードはすべて自前で書いた
- Better AuthはValsとも相性が良く、Val Townコードに認証を追加するにはBetter Auth starter templateを使える
残った教訓
- 上流プロバイダーの稼働時間はサービスの稼働時間に直接影響するため、そのリスクにどれだけさらされているかを慎重に判断する必要がある
- ある製品が多くのユースケースに適して大きく成功していても、特定の問題には適さないことがある
- ソフトウェア環境は急速に変化し、必要なタイミングでは存在しなかった適切な解決策が、1年後に現れることもある
1件のコメント
Hacker Newsのコメント
自分より賢い人に、なぜ Postgres users テーブルをサードパーティのプロバイダに委ねる必要があるのか説明してほしい。
Hetzner VM上のテーブルを自分で維持することの何がそんなに難しいのか分からない。決済でもなく、ただいくつかのフィールドを持つデータにすぎないのに
SSO, SAML, SCIM, OIDC, OAuth, 2段階認証, パスワードレス認証, 検証トークンなどが加わり、各機能ごとによく使われるシステムとの派生的な統合まで求められる。うちの会社ではしばらくの間、サポートエンジニアの時間の半分が自前の認証システムに関するありとあらゆるSSO問題の対応に消えていた
そうすれば「これは自分で実装しても価値がない」と感じる要件は全部その魔法のブラックボックスに押し込められる
エンタープライズ規模では違ってくるのかもしれない
Better AuthのBereketです。自分もまさにこの問題を解決するために Better Auth を始め、その後会社になった。
他の人たちが同じ価値を得ているのを見るのはいつもうれしい。まだやることは多いので、何を改善するとよいか知りたい
「複雑なシステムを作りながら学ぶ厳しい教訓は、その信頼性が中核部品の信頼性の最小値になることだ」という話よりさらに悪い。
実際には、クリティカルパス上にあるすべての構成要素の 可用性の積 が全体の可用性になる。ソフトウェア、認証レイヤー、クラウドプロバイダがそれぞれ99%の可用性で、そのうち1つでも落ちればサービス全体が止まるなら、最終的な可用性は97%しかない。そういう構成要素が11個あれば、可用性の「ナイン」は1つも残らない。だから構成要素を減らし、信頼性の高い解法を選ぶことが重要で、このチームがその道を選んだのはよいことだ
以前に出たSupabase移行記事(https://blog.val.town/blog/migrating-from-supabase)も面白く読んだ。
長期的なエンジニアリング判断について率直で良い文章は少ないので、ブログを書き続けてほしい
最近似たようなプロセスを経験した。Stack Auth で始めたが、極端に厳しいレート制限と悪い性能のせいで本番では使えず、レート制限に引っかからなくても遅かった。
その後WorkOS AuthKitに移行し、はるかによく動き、有用なエンタープライズ機能も備えていた。それでも新しいプロジェクトならBetter Authのほうに惹かれる。外部認証プロバイダの状態と自分のユーザー状態を同期するのはバグの温床で、認証プロバイダ側に置く状態はできるだけ少ないほうがよいが、それでも一部は残る。JWTアクセストークンを数分ごとに更新するのもまた別のバグの温床で、認証を自分で制御できるなら、正直そんなことをする必要はない。WorkOSは完全なAPIではなく、課金アカウントごとに1製品と固定された環境数(staging、production、サポートに依頼すればもう1つ)という前提で作られている。リダイレクトURLのようなものもダッシュボードで許可リストに入れなければならず、エージェントが簡単に処理する方法はなさそうだ。認証を外注するのはあまり筋が良いとは思えない。状態を複数のサービスに細かく分散させないほど、問題は減る。決済のように避けられない場合や、性能上の理由で特殊なデータベースが必要な場合もあるが、良いライブラリがあるなら認証でそうする理由は本当にない。サービスを使えばもっと早く始められるという主張もあるが、自分が認証サービスで経験した問題は大規模さとは関係がなく、その大半はリリース前から起きていた
Clerk を使っているが、かなり不満がある。まともなRBACがない。
役割がユーザー自身ではなく組織にひも付いているので、グローバル管理者のような概念を持てず、任意のキー・バリューの組をmetadataに保存する形で回避しなければならない。ここ数週間から数か月の間にもダウンタイムが何度もあり、そのたびにアプリ全体が失敗した。今後また使うかどうかはよく考えると思う
初期に Lucia を選んで本当によかったと感じている。ライブラリは事実上終了し、認証を自分で管理・ホストする方法をドキュメントと小さなユーティリティで置き換えた。
認証はいつも、自分で扱えない大きくて恐ろしいもののように語られるが、セキュリティと基本的なソルト処理がどう動くかを1週間ほど学んでみると、全体の仕組みにずっと自信が持てるようになった
ライブラリを廃止して、認証をゼロから実装するための学習資料に切り替えたときのことを覚えている。素晴らしい判断だったし、作者をとても尊敬している
ClerkとBetter Authの比較 は、ほとんど不公平だとすら言える。片方はサービスで、もう片方はライブラリなので、リンゴとオレンジの比較だ。
スタックに統合されるすべてのサードパーティサービスは責任の重荷になるし、ライブラリも同様だが程度は小さい。今こそ、より多くのサービスがライブラリに置き換わるべき時で、Better Authはそのやり方をうまく示している。フロントエンド、バックエンド、データベースに統合されるライブラリである点がよい
Tomの記事はいつも読む価値がある。
Auth0 や passportjs を覚えている人はいるだろうか? 認証サービスの変化に終わりはないが、標準も変わり続けるので仕方ないのだろう