Next.jsのAPI Routes機能でRate Limitをかける

Rate Limit とは一定時間内に実行可能な呼出回数を意味します。

WebAPIを連続で実行すると 429 Too Many Requests がレスポンスされる時がありますが、それを指します。1分間あたり30回(認証していない場合は10回など)までOKであったり、エンドポイントの機能、またその重要度によって制限内容はまちまちです。

制限をかける意図としては、APIサーバのパフォーマンスのため、ブルートフォース攻撃の対処などが挙げられるかと思います。

前置きが長くなりましたが、標題の内容に移ります。

Next.jsのAPI Routes機能にRate Limitをかける方法ですが、Next.jsのリポジトリ中のexamplesに挙げられています。

https://github.com/vercel/next.js/tree/canary/examples/api-routes-rate-limit

この例では、シンプルにLRUキャッシュ(Least Recently Used, 直近に参照した時刻が一番古いものを捨てる)でリクエスト元を一意に特定する情報と一定時間内にリクエストを組みで保持しておき、回数が制限回数を越えれば 429 を返し、一定時間経過後に破棄するような仕組みで実装しています。(大規模なサービスで取り入れる場合はキャッシュ先にRedisとかを使うのが通例か)

なお、上記の例では取りあげられていませんが、リクエストのIPアドレス単位で制限をかける方法を紹介している記事も貼っておきます。

https://zenn.dev/hasehiro0828/articles/8a5212198840cd

実装もシンプルで、既存のプロジェクトにも導入しやすいように思います。全てのWebAPIにかけずとも匿名ユーザーが実行できるパブリックなWebAPIだけでも優先してかけておいた方が良いでしょう。特にログインとか。

パッケージのメモ

上記の2つの例で利用されているパッケージをメモしておきます。

lru-cache
@typess/lru-cache (TypeScript使っている場合)

# リクエストのIPアドレス
request-ip
@types/request-ip (TypeScript使っている場合)