Install @nestjs/throttler, import ThrottlerModule with a ttl in milliseconds and a limit, then bind ThrottlerGuard globally with APP_GUARD. Add trust proxy if you sit behind a load balancer, so the tracker sees real client addresses. Use SkipThrottle and Throttle for exceptions.
Setup steps
The NestJS rate limiting docs describe this flow:
- Install the package.
- Configure ThrottlerModule with forRoot or forRootAsync. ttl is the time to live in milliseconds, and limit is the maximum number of requests within that window.
- Bind ThrottlerGuard. Any guard binding works. To apply it globally, register it as an APP_GUARD provider.
npm i --save @nestjs/throttler
@Module({
imports: [
ThrottlerModule.forRoot({
throttlers: [{ ttl: 60000, limit: 10 }],
}),
],
providers: [{ provide: APP_GUARD, useClass: ThrottlerGuard }],
})
export class AppModule {}
Several windows at once
You can define named throttlers, for example 3 calls per second, 20 per 10 seconds and 100 per minute. Short windows catch bursts, long windows catch steady scraping. Reference the names in the Throttle and SkipThrottle decorators to change them per route or controller.
Per route decisions
| Route type | Suggested approach |
|---|---|
| Login, password reset, signup | Tight limit, short and long windows |
| Public read endpoints | Moderate limit |
| Health checks | SkipThrottle |
| Webhooks from known senders | Separate handling, since senders may share addresses |
SkipThrottle disables the throttler for a class or one route, and the docs show you can negate skipping for a single route inside a skipped class.
The proxy problem
The docs say that if your app runs behind a proxy, you should configure the HTTP adapter to trust the proxy. Enabling trust proxy lets you retrieve the original IP from X-Forwarded-For, and you can override getTracker in a guard subclass to use that header instead of req.ip. For Express the doc example sets trust proxy to loopback.
If you skip this, every request may look like it comes from the proxy, so one noisy client exhausts the limit for everyone, or the limit is far too lax. Be as specific as you can about which proxies to trust. Read Express trust proxy for why a loose value lets clients forge addresses.
Storage
The throttler keeps counts in storage, and the docs include a section on custom storages. With several app instances, make sure counts are shared, otherwise each instance enforces its own limit. For the Fastify platform equivalent, see Fastify rate limit stores.
What rate limits do not fix
They slow guessing, they do not stop a single expensive request. Combine them with body and header limits and timeouts. See API resource limits beyond rate limiting and how to set up API rate limiting.
Safeguard's API security scanning and policies can check whether endpoints enforce limits. Free scan: gold.safeguard.sh/scan.
Quick check
Is ttl in seconds?
In the NestJS docs example, ttl is in milliseconds, so 60000 means one minute.
Do I need getTracker if I enable trust proxy?
Often not, since req.ip then reflects the forwarded address. The docs show overriding getTracker as another way to read the header.
Sources
Last reviewed: 19 October 2026.