Skip to Content
HeronJS 3.7 with fully support Typescript 6 is released & now is ESM native 🎉
DocumentationResilienceRate Limiter

Overview

The @RateLimiter decorator restricts the number of incoming requests to a route within a defined time window. Once the limit is exceeded, subsequent requests are rejected with an appropriate status code.


Import

import { RateLimiter } from '@heronjs/common';

Signature

@RateLimiter({ windows: number; // Time window in milliseconds max: number; // Max number of requests allowed in the window key: (req) => string; // Function to extract a unique key (IP, token, user-id, etc.) })
PropertyTypeDescription
windowsnumberDuration of the rate-limit window (in milliseconds).
maxnumberMaximum allowed requests per window.
key(req) => stringReturns a unique identifier for the client.

Key Extraction Examples

The key callback receives the raw Express HttpRequest object (rq). You can extract any header or property to differentiate clients.

1. Rate limit by IP address

@Get({ uri: '/liveness' }) @RateLimiter({ windows: 60000, max: 5, key: (rq) => `${rq.ip}` }) liveness(@Queries() a: {}): Observable<OutputProps> { }

2. Rate limit by Authorization header

@Get({ uri: '/secure-data' }) @RateLimiter({ windows: 30000, max: 3, key: (rq) => `${rq.headers['authorization'] ?? 'anonymous'}`, }) secureData(@Queries() a: {}): Observable<OutputProps> { }

3. Rate limit by custom header (e.g., x-api-key)

@Get({ uri: '/api' }) @RateLimiter({ windows: 60000, max: 10, key: (rq) => `${rq.headers['x-api-key'] ?? rq.ip}`, }) apiEndpoint(@Queries() a: {}): Observable<OutputProps> { }

4. Combining IP and User-Agent

@Get({ uri: '/search' }) @RateLimiter({ windows: 60000, max: 20, key: (rq) => `${rq.ip}-${rq.headers['user-agent'] ?? 'unknown'}`, }) search(@Queries() a: {}): Observable<OutputProps> { }

Full Example with Circuit Breaker

import { Get, Queries, RateLimiter, CircuitBreaker } from '@heronjs/core'; import { Observable, of } from 'rxjs'; @Get({ uri: '/liveness' }) @RateLimiter({ windows: 60000, max: 1, key: (rq) => `${rq.ip}` }) // @CircuitBreaker<HealthCheckRest>({ threshold: 3, cooldown: 60000, fallback: 'fallback' }) liveness(@Queries() a: {}): Observable<OutputProps> { } fallback(): Observable<{ status: string }> { }); }

Important Notes

  • The rate-limiter uses an in-memory sliding-window counter. Restarting the process resets all counters.
  • When the limit is exceeded, the framework responds with HTTP 429 Too Many Requests.
  • Combine @RateLimiter with @CircuitBreaker for advanced resilience patterns (see the Circuit Breaker documentation).
Last updated on