g14o
Packages@g14o/ratelimit

Route handlers & middleware

withRateLimit, checkRateLimit, per-user limits, and custom identifiers.

App Router route

Pass a tier to select a built-in limit profile. See default tiers for built-in limits.

app/api/chat/route.ts
import { withRateLimit } from "@/lib/ratelimit";

export const POST = withRateLimit(
  async (req) => Response.json({ ok: true }),
  { tier: "moderate" }
);

Manual check (middleware or custom flow)

Use checkRateLimit when you are not wrapping a route handler:

app/api/chat/route.ts
import { checkRateLimit } from "@/lib/ratelimit";

export async function POST(req: Request) {
  const result = await checkRateLimit(req, { tier: "strict" });
  if (!result.ok) {
    return Response.json({ error: "Too many requests" }, { status: 429 });
  }
  // ...
}

Per-user rate limit

Use a verified identity from your auth provider — not client-controlled headers.

app/api/chat/route.ts
import { withUserRateLimit } from "@/lib/ratelimit";
import { getSession } from "@/lib/auth";

export const POST = withUserRateLimit(
  async (req) => Response.json({ ok: true }),
  async (req) => {
    const session = await getSession(req);
    return session?.user.id ?? null;
  },
  { tier: "auth" }
);

Custom identifier

app/api/chat/route.ts
import { withRateLimit } from "@/lib/ratelimit";

export const GET = withRateLimit(
  async (req) => Response.json({ ok: true }),
  {
    tier: "lenient",
    identifierFn: async (req) =>
      req.headers.get("x-api-key") ?? "anonymous",
  }
);

On this page