Skip to content

Rate Limiter

npm

@gramio/rate-limit protects your bot handlers from spam and abuse using sliding-window rate limiting. Unlike a manual if (!await ctx.rateLimit(...)) return pattern, this plugin uses GramIO's macro system — handlers declare their limit inline as an options object. No boilerplate, no clutter.

Installation

bash
npm install @gramio/rate-limit
bash
yarn add @gramio/rate-limit
bash
pnpm add @gramio/rate-limit
bash
bun add @gramio/rate-limit

Usage

ts
import { Bot } from "gramio";
import { rateLimit } from "@gramio/rate-limit";

const bot = new Bot(process.env.BOT_TOKEN!)
    .extend(
        rateLimit({
            onLimitExceeded: async (ctx) => {
                if (ctx.is("message")) await ctx.reply("Too many requests, slow down!");
            },
        }),
    );

// Each handler declares its own throttle limits via the options object:
bot.command("pay", (ctx) => {
    // process payment...
}, { rateLimit: { limit: 3, window: 60 } });

bot.command("help", (ctx) => ctx.reply("Here is the help text"), {
    rateLimit: {
        id: "help",          // explicit key — defaults to event type + user id
        limit: 20,
        window: 60,
        onLimitExceeded: (ctx) => ctx.reply("Too many /help requests!"),
    },
});

await bot.start();

Custom storage

The plugin ships with in-memory storage out of the box (no external dependencies needed for development). For production, plug in any @gramio/storages-compatible adapter:

ts
import { rateLimit } from "@gramio/rate-limit";
import { redisStorage } from "@gramio/storage-redis";
import { Redis } from "ioredis";

const bot = new Bot(process.env.BOT_TOKEN!)
    .extend(
        rateLimit({
            storage: redisStorage(new Redis()),
            onLimitExceeded: async (ctx) => {
                if (ctx.is("message")) await ctx.reply("Slow down!");
            },
        }),
    );
ts
import { rateLimit } from "@gramio/rate-limit";
import { inMemoryStorage } from "@gramio/storage";

const bot = new Bot(process.env.BOT_TOKEN!)
    .extend(
        rateLimit({
            storage: inMemoryStorage(), // explicit, same as default
        }),
    );

API

rateLimit(options?)

Returns a GramIO plugin that registers the rateLimit macro.

OptionTypeDescription
storageStorageKey-value storage adapter. Default: in-memory
key(ctx) => stringCustom key function. Default: "${eventType}:${from.id}"
onLimitExceeded(ctx) => unknownDefault callback when limit is exceeded

Per-handler options (rateLimit macro)

Pass as the third argument to any handler method:

ts
bot.command("pay", handler, {
    rateLimit: {
        id?: string;           // Key override. Defaults to eventType:userId
        limit: number;         // Max requests per window
        window: number;        // Window size in seconds
        onLimitExceeded?: (ctx) => unknown; // Override global callback
    }
});
FieldTypeDefaultDescription
idstringevent type + user idCustom rate limit key
limitnumberMaximum allowed requests
windownumberWindow size in seconds
onLimitExceededfunctionglobal optionPer-handler override callback