Files
suaveplan/packages/api-stack/api/api-plugin-rate-limit
2026-05-27 23:29:53 +01:00
..
2026-05-27 23:29:53 +01:00
2026-05-27 23:29:53 +01:00
2026-05-27 23:29:53 +01:00
2026-05-27 23:29:53 +01:00
2026-05-27 23:29:53 +01:00
2026-05-27 23:29:53 +01:00
2026-05-27 23:29:53 +01:00
2026-05-27 23:29:53 +01:00

@suaveplan/api-plugin-rate-limit - Rate-limit plugin for @suaveplan/api. Wraps @suaveplan/rate-limiter as a definePlugin descriptor: per-route + per-tenant configuration, parameterised path matcher, IP whitelist, tenant multiplier applied to numeric limit, Hono middleware factory, 429 + Retry-After + X-RateLimit-* / RateLimit-* headers, OTel counters, RFC 7807 Problem+JSON body. Registers rateLimitService in the host ServiceRegistry.

Rate-limit plugin for @suaveplan/api. Wraps @suaveplan/rate-limiter as a definePlugin descriptor exposing per-route + per-tenant configuration, parameterised path matching, IP whitelist, applied tenant multiplier, Hono middleware, X-RateLimit-* / RateLimit-* / Retry-After headers, RFC 7807 Problem+JSON 429 body, and OTel counters / histogram. Registers a typed rateLimitService slot in the host ServiceRegistry so sibling plugins can run manual checks.

Documentation tree

  • error-codes — Provides the stable, namespaced error-code registry every failure path in @suaveplan/api-plugin-rate-limit reports th…
    • error-codes — Provides the stable, namespaced error-code registry every failure path in @suaveplan/api-plugin-rate-limit reports th…
  • headers — Builds the HTTP response headers and Problem+JSON body the rate-limit middleware writes onto every response (allowed AN…
    • headers — Builds the HTTP response headers and Problem+JSON body the rate-limit middleware writes onto every response (allowed AN…
  • context-augmentation — Augments Hono's ContextVariableMap interface so handlers calling c.get("rateLimit") get a typed RateLimitDecision…
  • rate-limit — Constructs a Hono MiddlewareHandler that consults a RateLimitService on every request, emits the configured `X-Rate…
  • otel — Builds (and caches) the bundle of OpenTelemetry instruments the rate-limit plugin emits on every check. Operators wirin…
    • instruments — Builds (and caches) the bundle of OpenTelemetry instruments the rate-limit plugin emits on every check. Operators wirin…
  • path-matcher — Compiles a Hono-style path pattern string into a regular expression
    • path-matcher — Compiles a Hono-style path pattern string into a regular expression
  • plugin — Factory that returns a typed PluginDescriptor for the rate-limit plugin, ready to be passed to @suaveplan/api's plu…
    • plugin — Factory that returns a typed PluginDescriptor for the rate-limit plugin, ready to be passed to @suaveplan/api's plu…
  • schemas — Validates the caller-supplied RateLimitPluginOptions at the boundary and fills in defaults for every optional field,…
    • options — Validates the caller-supplied RateLimitPluginOptions at the boundary and fills in defaults for every optional field,…
  • rate-limit-service — Wraps the universal @suaveplan/rate-limiter core in the plugin's policy layer: IP whitelist, tenant bypass, tenant mu…
  • registry-augmentation — Augments the ServiceRegistry interface owned by @suaveplan/api-plugin/service-registry so consumers see the `rateLi…
  • types — Defines the public type surface every other module in the package references — the caller-facing `RateLimitPluginOption…
    • types — Defines the public type surface every other module in the package references — the caller-facing `RateLimitPluginOption…

Install

bun add @suaveplan/api-plugin-rate-limit

Quick start

import { createApi } from "@suaveplan/api";
import { createRateLimitPlugin } from "@suaveplan/api-plugin-rate-limit";

const api = createApi();
api.use(
    createRateLimitPlugin({
        defaultLimit: 100,
        defaultWindowMs: 60_000,
        routes: [
            {
                path: "/api/login",
                method: "POST",
                limit: 5,
                windowMs: 60_000,
                id: "login",
            },
            { path: "/api/users/:id", limit: 30, windowMs: 60_000 },
        ],
        tenants: [
            { tenantId: "enterprise", multiplier: 10 },
            { tenantId: "internal", bypass: true },
        ],
        ipWhitelist: ["127.0.0.1"],
        headerStyle: "both",
    })
);

Every request flowing through the host Hono app is now rate-limited. Responses carry both legacy X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset and IETF RateLimit-Limit / RateLimit-Remaining / RateLimit-Reset headers. Denied requests return 429 with Content-Type: application/problem+json and a Retry-After header.

Manual service.check(...) from sibling plugins

import {
    rateLimitExceeded,
    type RateLimitService,
} from "@suaveplan/api-plugin-rate-limit";

const service = ctx.getService("rateLimitService") as RateLimitService;
const decision = await service.check({
    ip,
    tenantId,
    path: "/api/billing/invoice",
    method: "POST",
});
if (!decision.allowed) throw rateLimitExceeded(decision);

The 3-way plug-and-play contract

This package follows the same contract every @suaveplan/api-plugin-* package follows: it owns its boundary Zod schemas (RateLimitPluginOptionsSchema), registers a typed slot in the host ServiceRegistry (rateLimitService), and installs a global Hono middleware via app.use("*", rateLimit({ service })) from its canonical 6-step onInit lifecycle (resolve services → build storage → construct service → register slot → install middleware → log readiness).

Modules

Status

0.1.0 — initial ship. Surface is final for the 0.1.x line.