LogoUsefulKey
How to

Add Rate Limiting

Learn how to add rate limiting to your API keys to control usage.

Rate Limiting Basics

Rate limiting helps you control how often API keys can be used. UsefulKey supports two types of rate limiting: fixed windows and token buckets.

Fixed Window Rate Limiting

A fixed window limits the number of requests in a specific time period. For example, "100 requests per minute".

import { usefulkey, MemoryKeyStore, MemoryRateLimitStore, ratelimit } from "usefulkey";

const uk = usefulkey({
  adapters: {
    keyStore: new MemoryKeyStore(),
    rateLimitStore: new MemoryRateLimitStore(),
  },
}, {
  plugins: [
    ratelimit({
      default: {
        kind: "fixed",
        limit: 100,     // Maximum 100 requests
        duration: "1m"  // Per minute
      }
    })
  ]
});

Token Bucket Rate Limiting

A token bucket allows bursts of requests but maintains an overall rate. Tokens are added at a steady rate, and each request consumes one token.

const uk = usefulkey({
  adapters: {
    keyStore: new MemoryKeyStore(),
    rateLimitStore: new MemoryRateLimitStore(),
  },
}, {
  plugins: [
    ratelimit({
      default: {
        kind: "tokenBucket",
        capacity: 50,        // Bucket holds up to 50 tokens
        refill: {
          tokens: 10,       // Add 10 tokens
          interval: "1m"    // Every minute
        }
      }
    })
  ]
});

Using Rate Limited Keys

When rate limiting is enabled, you must provide a namespace when verifying keys:

// Create a key
const { result: keyData } = await uk.createKey();

// Verify with namespace (required for rate limiting)
const { result: verification } = await uk.verifyKey({
  key: keyData.key,
  namespace: "api"  // Group rate limits by namespace
});

if (verification.valid) {
  console.log("Request allowed");
} else {
  console.log("Rate limited:", verification.reason);
}

Per-Key Rate Limiting

You can also set rate limits for individual keys:

// Verify with custom rate limit for this specific call
const { result: verification } = await uk.verifyKey({
  key: keyData.key,
  namespace: "api",
  rateLimit: {
    kind: "fixed",
    limit: 5,
    duration: "1m"
  }
});

Rate Limit Results

When rate limiting blocks a request, you'll get:

{
  valid: false,
  reason: "rate_limited"
}

Namespaces Explained

Namespaces let you have separate rate limits for different parts of your API:

// Different limits for different API endpoints
await uk.verifyKey({ key: keyData.key, namespace: "auth" });     // Login endpoints
await uk.verifyKey({ key: keyData.key, namespace: "search" });   // Search endpoints
await uk.verifyKey({ key: keyData.key, namespace: "admin" });    // Admin endpoints

Complete Example

import { usefulkey, MemoryKeyStore, MemoryRateLimitStore, ratelimit } from "usefulkey";

async function rateLimitedExample() {
  const uk = usefulkey({
    adapters: {
      keyStore: new MemoryKeyStore(),
      rateLimitStore: new MemoryRateLimitStore(),
    },
  }, {
    plugins: [
      ratelimit({
        default: {
          kind: "fixed",
          limit: 10,      // 10 requests
          duration: "1m"  // per minute
        }
      })
    ]
  });

  // Create a key
  const { result: keyData } = await uk.createKey();

  // Try multiple requests
  for (let i = 0; i < 12; i++) {
    const { result: verification } = await uk.verifyKey({
      key: keyData.key,
      namespace: "api"
    });

    if (verification.valid) {
      console.log(`Request ${i + 1}: ✓ Allowed`);
    } else {
      console.log(`Request ${i + 1}: ✗ ${verification.reason}`);
    }
  }
}

rateLimitedExample();

This will show the first 10 requests as allowed, and requests 11-12 as rate limited.