LEFログ:学習記録ノート

leflog: 学習の記録をどんどんアップしていきます

SupabaseとPrismaとNextAuth(Auth.js)を同時に使うときはConnection poolingの設定もしよう

コネクションプーリング(イメージ図)

TL;DR

  • リモートのSupabaseとNextAuthを連携するには、Prismaでコネクションプーリングの設定をする必要があるよ
  • そのためにはPrismaにコードを付け足して、環境変数を設定する必要があるよ
  • ローカルのSupabaseに接続するときはこの設定は必要ないよ

経緯

最近Next.jsとPrismaとSupabaseとNextAuth(Auth.js)*1を組み合わせて認証機能を実装しようとしていたのですが、困ったことがありました。

それは、ローカルで立ち上げたアプリでは認証できるのに、リモート(本番環境)で立ち上げたアプリでは認証がうまくいかないという問題です。

リモートで認証しようとすると、リダイレクトの画面で「別のアカウントで試してね」という表示が出てきてログインできません。

開発環境としては次のようになっていました。

  • ローカルで立ち上げたNext.jsアプリ → ローカルのSupabaseに繋げる
  • リモートで立ち上げたNext.jsアプリ → リモートのSupabaseに繋げる

ネットで検索してもあまり情報がなかったので、今回ブログにまとめてみました。

問題箇所の特定

問題箇所を特定するために、次のステップを踏みました。

NextAuthでGoogle認証ができるように設定していたところ、ローカル環境では問題なく認証できるのに、本番環境では認証できないという問題に遭遇する。

↓

初めはGoogle側で自分が何か設定ミスをしているのかもしれないと考えていたが、本番環境ではDiscordの認証までできなくなっていることを確認する。

↓

NextAuthまたはVercelまたはSupabaseの問題であると絞り込む。

↓

更にローカルではエラーが再現しなかったため、VercelかSupabaseかの問題であることまでを絞り込む。

↓

VercelおよびSupabaseのログを読み、データベースとの接続が怪しいと当たりをつける。

↓

ローカル環境でもエラーを再現しようと試みる。

↓

ローカル上のNext.jsのenvファイルの環境変数を変更し、ローカルからリモートのSupabaseに接続を変えたところエラーが再現する。

↓

Vercel側の問題ではなく、Supabase側の問題だと特定する。

↓

SupabaseとPrismaのドキュメントを読んでコネクションプーリングの設定をしたところ、無事に本番環境でもGoogle認証ができるようになる。

これで、無事にリモート(Vercel上のNext.js)でも認証機能を実装できました。

なぜコネクションプーリングの設定が必要なのか?

ここからは推測ですが、Prismaの機能をフルで使うためにはこの設定が必要なのだと思われます。

Using Prisma with Supabase | Prisma Docs

We strongly recommend using pgbouncer in addition to DIRECT_URL. You will gain the great developer experience of the Prisma CLI while also allowing for connections to be pooled regardless of deployment strategy. While this is not strictly necessary for every app, serverless solutions will inevitably require connection pooling.

Prisma schema API (Reference) | Prisma Docs

Connection URL for direct connection to the database. If you use a connection pooler URL in the url argument (for example, if you use the Data Proxy or pgBouncer), Prisma CLI commands that require a direct connection to the database use the URL in the directUrl argument. The directUrl property is supported by Prisma Studio from version 5.1.0 upwards.

Supabaseのログを見ると、「pgBouncerがうまく機能していない」というような内容でした。

そしてPrismaは「pgBouncerを使うためにはdirectUrlを使ってデータベースに直接接続する必要がある」とドキュメントに書いています。

逆にローカル環境同士でうまく動いたのが謎ですが、おそらくローカルで動くSupabaseとリモートで動いているSupabaseで中身がちょっと違うのだと思います。

コネクションプーリングは(すごく簡略化して説明すると)「ずっと接続を維持しておくための仕組み」なので、リモートでは接続が切れやすい設定になっているんじゃないのかな〜と思いました。

まとめ

ローカルでは問題なく動くのに、リモートでは動かない事象に遭遇してとても不思議でした。

エラーの発生箇所を徐々に絞り込むことで解決できたので良かったです。

問題を解決するためには、確実に動いている地点を確かめるのが大事だと改めて理解しました。

また、BaaS(Backend as a Service)を使う場合には、リモートとローカルで環境を分けると設定が色々大変なことが分かりました。

(Supabaseを使った開発フローについてもそのうち記事を作りたいと思います。)

設定方法については次のリンク先の記事をご参考ください。

参考記事

PrismaとSupabaseの公式ドキュメントです。

記事に従ってConnection Poolingの設定までおこなえば無事に動きます。Vercel側にも環境変数を設定してあげましょう。

*1:最近NextAuthからAuth.jsに名前が変わったらしい