This package has been deprecated

Author message:

Package has been renamed to @convex-dev/rate-limiter

@convex-dev/ratelimiter
TypeScript icon, indicating that this package has built-in type declarations

0.1.7 • Public • Published

Convex Rate Limiter Component

npm version

Note: Convex Components are currently in beta

Application-level rate limiting.

  • Type-safe
  • Configurable for fixed window or token bucket algorithms
  • Efficient storage and compute
  • Configurable sharding for scalability
  • Transactional evaluation
  • Fairness guarantees via credit "reservation"
  • Opt-in "rollover" or "burst" allowance via "token bucket" config
  • Fails closed, not open

Definition:

const rateLimiter = new RateLimiter(components.ratelimiter, {
  // One global / singleton rate limit, using a "fixed window" algorithm.
  freeTrialSignUp: { kind: "fixed window", rate: 100, period: HOUR },
  // A per-user limit, allowing one every ~6 seconds.
  // Allows up to 3 in quick succession if they haven't sent many recently.
  sendMessage: { kind: "token bucket", rate: 10, period: MINUTE, capacity: 3 },
  failedLogins: { kind: "token bucket", rate: 10, period: HOUR },
  // Use sharding to increase throughput without compromising on correctness.
  llmTokens: { kind: "token bucket", rate: 40000, period: MINUTE, shards: 100 },
  llmRequests: { kind: "fixed window", rate: 3, period: MINUTE },
});

Usage:

// Restrict how fast free users can sign up to deter bots
const status = await rateLimiter.limit(ctx, "freeTrialSignUp");

// Limit how fast a user can send messages
const status = await rateLimiter.limit(ctx, "sendMessage", { key: userId });

// Automatically throw an error if the rate limit is hit
await rateLimiter.limit(ctx, "failedLogins", { key: userId, throws: true });

// Consume multiple in one request to prevent rate limits on an LLM API.
const status = await rateLimiter.limit(ctx, "llmTokens", { count: tokens });

// Reserve future capacity instead of just failing now
if (!args.skipCheck) {
  const status = await rateLimiter.limit(ctx, "llmRequests", { reserve: true });
  if (status.retryAfter) {
    return ctx.scheduler.runAfter(status.retryAfter, internal.foo.bar, {
      skipCheck: true,
    });
  }
}

// Check a rate limit without consuming it
const status = await rateLimiter.check(ctx, "failedLogins", { key: userId });

// Reset a rate limit on successful login
await rateLimiter.reset(ctx, "failedLogins", { key: userId });

// Use a one-off rate limit config (when not named on initialization)
const config = { kind: "fixed window", rate: 1, period: SECOND };
await rateLimiter.limit(ctx, "oneOffName", { config, throws: true });

See this article for more information.

Pre-requisite: Convex

You'll need an existing Convex project to use the component. Convex is a hosted backend platform, including a database, serverless functions, and a ton more you can learn about here.

Run npm create convex or follow any of the quickstarts to set one up.

Installation

Install the component package:

npm install @convex-dev/ratelimiter

Create a convex.config.ts file in your app's convex/ folder and install the component by calling use:

// convex/convex.config.ts
import { defineApp } from "convex/server";
import ratelimiter from "@convex-dev/ratelimiter/convex.config";

const app = defineApp();
app.use(ratelimiter);

export default app;

Usage

Define your rate limits:

import { RateLimiter } from "@convex-dev/ratelimiter";
import { components } from "./_generated/api";

const rateLimiter = new RateLimiter(components.ratelimiter, {
  // One global / singleton rate limit
  freeTrialSignUp: { kind: "fixed window", rate: 100, period: HOUR },
  sendMessage: { kind: "token bucket", rate: 10, period: MINUTE, capacity: 3 },
});
  • You can safely generate multiple instances if you want to define different rates in separate places.

Use it from a mutation or action:

const { ok, retryAfter } = await rateLimiter.limit(ctx, "freeTrialSignUp");

Or if you want to rate limit based on a key:

await rateLimiter.limit(ctx, "sendMessage", { key: user._id, throws: true });

This call also throws an exception, so you don't have to check the return value.

Check out a full example here.

See this article for more information on usage and advanced patterns.

Readme

Keywords

Package Sidebar

Install

npm i @convex-dev/ratelimiter

Weekly Downloads

1

Version

0.1.7

License

Apache-2.0

Unpacked Size

198 kB

Total Files

83

Last publish

Collaborators

  • cowling
  • jordanhunt
  • gautamg795
  • emmaling27
  • nipunn
  • sujayakar
  • ikhare
  • ldanilek
  • ballingt
  • sshader
  • aritrakh
  • ianatconvex
  • erquhart
  • jamwt