# Overview

> Protect any API endpoint from abuse with Unkey's distributed rate limiting. No infrastructure required, just a single API call.

Rate limiting controls how many requests a user, IP, or any identifier can make in a given time window. Unkey provides distributed rate limiting that runs across the Unkey network without infrastructure for you to manage.

## When to use rate limiting

<CardGroup cols={2}>
  <Card title="Prevent abuse" icon="shield">
    Stop bad actors from hammering your endpoints or scraping your data.
  </Card>
  <Card title="Protect costs" icon="piggy-bank">
    Limit expensive operations (AI calls, database queries) before they blow up
    your bill.
  </Card>
  <Card title="Fair usage" icon="scale-balanced">
    Ensure no single user monopolizes shared resources.
  </Card>
  <Card title="Compliance" icon="file-contract">
    Enforce contractual limits (e.g., 10,000 requests/month on a Basic plan).
  </Card>
</CardGroup>

## How it works

<Steps>
  <Step title="Choose an identifier">
    Decide what you're limiting: a user ID, API key, IP address, organization,
    or any string that uniquely identifies the requester.
  </Step>
  <Step title="Set the limit">
    Define how many requests are allowed and over what duration. Example: 100
    requests per minute.
  </Step>
  <Step title="Check on each request">
    Call `limiter.limit(identifier)` and Unkey tells you whether to allow or
    reject the request.
  </Step>
</Steps>

## Quick example

<CodeGroup>

```ts TypeScript
import { Ratelimit } from "@unkey/ratelimit";

const limiter = new Ratelimit({
  rootKey: process.env.UNKEY_ROOT_KEY,
  namespace: "my-app", // Group related limits together
  limit: 10, // 10 requests...
  duration: "60s", // ...per minute
});

export async function handler(req: Request) {
  // Use any identifier: user ID, API key, IP, etc.
  const identifier = req.headers.get("x-user-id") ?? getClientIP(req);

  const { success, remaining, reset } = await limiter.limit(identifier);

  if (!success) {
    return new Response("Too many requests", {
      status: 429,
      headers: {
        "X-RateLimit-Remaining": "0",
        "X-RateLimit-Reset": reset.toString(),
      },
    });
  }

  // Request allowed, continue with your logic
  return new Response(`Hello! ${remaining} requests remaining.`);
}
```

```bash cURL
curl -X POST https://api.unkey.com/v2/ratelimit.limit \
  -H "Authorization: Bearer unkey_..." \
  -H "Content-Type: application/json" \
  -d '{
    "namespace": "my-app",
    "identifier": "user_123",
    "limit": 10,
    "duration": 60000
  }'
```

</CodeGroup>

## Standalone vs Key-attached rate limits

Unkey offers two ways to rate limit:

| Approach         | Best for                        | How it works                                                          |
| ---------------- | ------------------------------- | --------------------------------------------------------------------- |
| **Standalone**   | Any endpoint, public or private | You call `limiter.limit()` with any identifier                        |
| **Key-attached** | API key authenticated endpoints | Rate limits are configured per-key and checked during `keys.verify()` |

**Standalone** is what this section covers, it works anywhere, with or without API keys.

**Key-attached** rate limits are configured when you [create API keys](/platform/apis/features/ratelimiting/overview) and are automatically enforced during verification.

<Tip>
  You can use both. Standalone rate limits work well for public endpoints such
  as login and signup. Key-attached rate limits work well for authenticated API
  calls.
</Tip>

## What makes Unkey rate limiting different?

<AccordionGroup>
  <Accordion title="No infrastructure to manage" icon="server">
    No Redis clusters, no Upstash accounts, no connection strings. Install the
    SDK and call the API.
  </Accordion>

<Accordion title="Globally distributed" icon="globe">
  Requests are processed across Unkey's globally distributed infrastructure.
  Your rate limits are checked close to your users, not in a single region.
  Identifiers approaching their limit converge globally within seconds. See [how rate
  limiting works](/platform/ratelimiting/how-it-works#share-counts-across-regions).
</Accordion>

<Accordion title="Performance at scale" icon="gauge-high">
  See real-time performance metrics at
  [ratelimit.unkey.com](https://ratelimit.unkey.com), our global latency and
  throughput benchmarks updated live.
</Accordion>

<Accordion title="Timeout and fallback" icon="bolt">
  Configure custom timeout and fallback behavior for resilience when network
  issues occur.
</Accordion>

<Accordion title="Per-identifier overrides" icon="user-pen">
  Give specific users higher limits without changing code. "User X gets 1000/min
  instead of 100/min."
</Accordion>

  <Accordion title="Analytics built in" icon="chart-line">
    See which identifiers are hitting limits, when, and how often, in your
    Unkey dashboard.
  </Accordion>
</AccordionGroup>

## Get started

<Steps>
  <Step title="Create a root key">
    Go to [Settings → Root Keys](https://app.unkey.com/settings/root-keys) and
    create a new key with these permissions: - `ratelimit.*.create_namespace` -
    `ratelimit.*.limit`
  </Step>
  <Step title="Install the SDK">```bash npm install @unkey/ratelimit ```</Step>
  <Step title="Add to your code">
    See the [Next.js](/quickstart/ratelimiting/nextjs),
    [Bun](/quickstart/ratelimiting/bun),
    [Express](/quickstart/ratelimiting/express), or
    [Hono](/quickstart/ratelimiting/hono) guides for complete examples.
  </Step>
</Steps>

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart/ratelimiting/nextjs">
    Full walkthrough for your framework.
  </Card>
  <Card
    title="How it works"
    icon="arrows-split-up-and-left"
    href="/platform/ratelimiting/how-it-works"
  >
    Understand global consistency and response behavior.
  </Card>
  <Card
    title="Overrides"
    icon="sliders"
    href="/platform/ratelimiting/overrides"
  >
    Give specific users custom limits.
  </Card>
  <Card
    title="SDK Reference"
    icon="code"
    href="/libraries/ts/ratelimit/ratelimit"
  >
    All configuration options and methods.
  </Card>
</CardGroup>
