How to Configure Rate Limiting with Short, Medium, and Long TTL Limits in OpenWA

Configure short-, medium-, and long-TTL rate limiting in OpenWA by setting the RATE_LIMIT_SHORT_TTL, RATE_LIMIT_MEDIUM_TTL, and RATE_LIMIT_LONG_TTL environment variables, which override the defaults defined in src/config/configuration.ts and are consumed by the NestJS Throttler module in src/app.module.ts.

OpenWA implements a three-tier rate limiting strategy using NestJS Throttler to protect the WhatsApp API from abuse. This architecture allows you to define distinct time-to-live (TTL) windows and request limits for short-term bursts, medium-term sustained traffic, and long-term aggregate usage, all configurable via environment variables without modifying source code.

Understanding the Three-Tier Rate Limiting Architecture

OpenWA’s rate limiting system relies on three interconnected components: the central configuration file, security middleware constants, and the Throttler module registration.

Configuration Defaults in configuration.ts

The primary source of truth for rate limiting values resides in src/config/configuration.ts. Lines 66–76 define the api.rateLimit object, mapping environment variables to default values for all three tiers.

Tier Environment Variable (TTL) Environment Variable (Limit) Default TTL Default Limit
Short RATE_LIMIT_SHORT_TTL RATE_LIMIT_SHORT_LIMIT 1000 ms 10 requests
Medium RATE_LIMIT_MEDIUM_TTL RATE_LIMIT_MEDIUM_LIMIT 60000 ms 100 requests
Long RATE_LIMIT_LONG_TTL RATE_LIMIT_LONG_LIMIT 3600000 ms 1000 requests

Source: [src/config/configuration.ts](https://github.com/rmyndharis/OpenWA/blob/main/src/config/configuration.ts#L66-L76)

Security Constants Fallback

src/common/security/security.middleware.ts contains a fallback SecurityConfig.rateLimit object (lines 81–86) that mirrors the same default values. This ensures that if the configuration service fails to load, the application still maintains protective rate limiting boundaries.

Source: [src/common/security/security.middleware.ts](https://github.com/rmyndharis/OpenWA/blob/main/src/common/security/security.middleware.ts#L81-L86)

Module Registration in app.module.ts

The values are injected into the application through ThrottlerModule.forRootAsync in src/app.module.ts (lines 120–131). The factory function retrieves the TTL and limit values for each tier using ConfigService.get<number>() and registers three separate throttler instances.

Source: [src/app.module.ts](https://github.com/rmyndharis/OpenWA/blob/main/src/app.module.ts#L120-L131)

How to Configure Rate Limiting via Environment Variables

All rate limiting parameters are configurable at runtime through environment variables. Create or modify your .env file in the project root to override the defaults.


# Short-term burst protection (10 requests per second)

RATE_LIMIT_SHORT_TTL=1000
RATE_LIMIT_SHORT_LIMIT=10

# Medium-term protection (100 requests per minute)

RATE_LIMIT_MEDIUM_TTL=60000
RATE_LIMIT_MEDIUM_LIMIT=100

# Long-term protection (1000 requests per hour)

RATE_LIMIT_LONG_TTL=3600000
RATE_LIMIT_LONG_LIMIT=1000

After updating the environment variables, restart the OpenWA container or the Node.js process for the changes to take effect. The configuration is read once at startup and propagated through NestJS’s dependency injection system.

Implementation Details and Code Examples

How the Values Flow Through the Application

  1. Startup: ConfigModule loads configuration.ts and parses environment variables into the api.rateLimit namespace.
  2. Registration: ThrottlerModule.forRootAsync extracts the six values (three TTLs and three limits) using configService.get<number>().
  3. Enforcement: The throttler middleware applies the most restrictive limit that applies to the current request window.
  4. Headers: As implemented in src/main.ts, responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.

Example: Aggressive Short-Term Limits

To restrict short-term bursts to 5 requests per 2 seconds while keeping other tiers standard:


# .env

RATE_LIMIT_SHORT_TTL=2000
RATE_LIMIT_SHORT_LIMIT=5
RATE_LIMIT_MEDIUM_TTL=60000
RATE_LIMIT_MEDIUM_LIMIT=100
RATE_LIMIT_LONG_TTL=3600000
RATE_LIMIT_LONG_LIMIT=1000

Verify the headers with a test request:

curl -i http://localhost:2785/api/v1/health

Expected response headers:

X-RateLimit-Limit: 5
X-RateLimit-Remaining: 4
X-RateLimit-Reset: 2

Example: Per-Route Override with @Throttle

For specific controllers requiring different limits, use the @Throttle decorator from @nestjs/throttler to override the global configuration:

import { Controller, Get } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';

@Controller('webhook')
export class WebhookController {
  // Allow only 2 requests per minute for this endpoint
  @Get('validate')
  @Throttle(60, 2)  // ttl: 60 seconds, limit: 2 requests
  validateWebhook() {
    return { status: 'valid' };
  }
}

Example: Runtime Configuration Debugging

To verify the active rate limiting configuration programmatically:

import { ConfigService } from '@nestjs/config';
import { Injectable, Logger } from '@nestjs/common';

@Injectable()
export class RateLimitDebugService {
  constructor(private readonly configService: ConfigService) {}

  logLimits() {
    const shortTtl = this.configService.get<number>('api.rateLimit.shortTtl');
    const shortLimit = this.configService.get<number>('api.rateLimit.shortLimit');
    const mediumTtl = this.configService.get<number>('api.rateLimit.mediumTtl');
    const mediumLimit = this.configService.get<number>('api.rateLimit.mediumLimit');
    const longTtl = this.configService.get<number>('api.rateLimit.longTtl');
    const longLimit = this.configService.get<number>('api.rateLimit.longLimit');

    Logger.log(`Rate Limits - Short: ${shortLimit}req/${shortTtl}ms`);
    Logger.log(`Rate Limits - Medium: ${mediumLimit}req/${mediumTtl}ms`);
    Logger.log(`Rate Limits - Long: ${longLimit}req/${longTtl}ms`);
  }
}

Summary

  • OpenWA implements three-tier rate limiting (short, medium, long) via NestJS Throttler, configured through the ConfigService.
  • Default values are defined in src/config/configuration.ts (lines 66–76) and mirrored in src/common/security/security.middleware.ts (lines 81–86).
  • Override defaults by setting RATE_LIMIT_SHORT_TTL, RATE_LIMIT_MEDIUM_TTL, and RATE_LIMIT_LONG_TTL environment variables with their corresponding *_LIMIT values.
  • The throttler is registered in src/app.module.ts (lines 120–131) using ThrottlerModule.forRootAsync.
  • Use the @Throttle decorator to override global limits for specific routes.
  • Changes require an application restart to take effect.

Frequently Asked Questions

What are the default rate limiting values in OpenWA?

By default, OpenWA enforces three tiers: short (10 requests per 1000ms), medium (100 requests per 60000ms), and long (1000 requests per 3600000ms). These defaults are hardcoded in src/config/configuration.ts and serve as fallbacks if environment variables are not set.

How do I apply different rate limits to specific API endpoints?

Apply the @Throttle(ttl, limit) decorator to individual controller methods. This overrides the global configuration for that specific route. For example, @Throttle(60, 2) restricts the endpoint to 2 requests per minute regardless of the global short, medium, or long settings.

Where can I see the current rate limit status for my requests?

OpenWA includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers in HTTP responses. These headers indicate the current tier’s maximum requests, remaining quota, and seconds until the limit resets, respectively.

Do I need to restart OpenWA after changing rate limit environment variables?

Yes. OpenWA reads the configuration once at startup. After modifying .env or your container’s environment variables, you must restart the application process or container for the new TTL and limit values to take effect.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →