Files
suaveplan/packages/api-stack/api/api-host/src/admin-api/rate-limiter.md
2026-05-27 23:29:53 +01:00

2.3 KiB

rate-limiter.ts

Purpose

AdminRateLimiter enforces the design §8.4 per-principal rate limits on every admin endpoint. Read endpoints share a 60-calls-per-minute bucket; destructive endpoints share a 1-per-minute bucket. Both buckets are scoped per principal id so a misbehaving operator cannot starve the host of admin throughput for everyone else.

The limiter is a thin wrapper around @suaveplan/rate-limiter's TokenBucket — one bucket per (principalId, kind) pair, allocated lazily on first contact. The refill rate is set so the bucket starts full and drains to zero after capacity consecutive calls in a minute; refill is linear, so a steady stream is permitted at the documented rate. Bursts up to capacity are allowed.

Features

  • Per-principal isolation — one bucket pair per id.
  • Lazy allocation — principals that never hit admin are zero-cost.
  • Token-bucket refill maps capacity calls to one minute.
  • Injectable clock for deterministic tests.

Usage: Basic

import { AdminRateLimiter } from "@suaveplan/api-host/admin-api";

const limiter = new AdminRateLimiter(60, 1);
limiter.consume("alice", "read");        // true
limiter.consume("alice", "destructive"); // true
limiter.consume("alice", "destructive"); // false (until refill)

Usage: Advanced

let now = 0;
const limiter = new AdminRateLimiter(60, 1, () => now);
limiter.consume("alice", "destructive"); // true
limiter.consume("alice", "destructive"); // false
now = 60_001;
limiter.consume("alice", "destructive"); // true — refilled

API Reference

  • new AdminRateLimiter(readPerMinute, destructivePerMinute, clock?)
  • consume(principalId, kind): boolean — true on success, false when rate-limited.

Implementation Notes

TokenBucket's consume(1) updates the bucket's internal counter and returns a RateLimitResult. The admin API only cares about the allowed boolean — it surfaces 429 + Retry-After purely from constants when consume returns false.

The principal-id key is the rate-limit cardinality bound. A deployment with many distinct admin principals carries a small memory cost (~80 bytes per bucket pair) — gateways should rate-limit admin traffic at the edge before it reaches the host if extreme multi-tenant cardinality is anticipated.