Security

Rate limiter

Get started | Expo Starter

Enable rate limiter for REST API

To enhance the security of your API, consider implementing throttling with Vercel/KVM. This method helps safeguard against brute-force attacks by limiting the number of requests a user can make within a given time frame, effectively preventing malicious attempts to access your system.

server.ts
import { kv } from "@vercel/kv";
const limit = 10;
const window_seconds = 60;
 
const rateLimit = t.middleware(async ({ ctx, next }) => {
  const interval = Math.floor(Date.now() / 1000 / window_seconds);
  const key = `rate-limit:${ctx.session?.id}:${interval}`;
 
  const current = await kv.incr(key, { ex : window_seconds, nx: true});
 
  if (current > limit) {
    throw new TRPCError({
      code: "TOO_MANY_REQUESTS",
      message: "You are being rate limited.",
    });
  }
 
  return next();
});
export const rateLimitedProcedure = t.procedure.use(rateLimit);

For Self-hosted, you can use Redis or Memcached to implement rate limiting.

terminal
  pnpm install ioredis

Add REDIS_URL to environment variable :

.env
REDIS_URL=redis://default:password@localhost:6379

Edit the server.ts file to implement rate limiting with Redis:

server.ts
import Redis from 'ioredis';
import { TRPCError } from '@trpc/server';
 
const redis = new Redis(); // Connects to the default Redis server (localhost:6379)
const limit = 10;
const window_seconds = 60;
 
const rateLimit = t.middleware(async ({ ctx, next }) => {
  const interval = Math.floor(Date.now() / 1000 / window_seconds);
  const key = `rate-limit:${ctx.session?.id}:${interval}`;
  
  const current = await redis.incr(key);
  
  if (current === 1) {
    await redis.expire(key, window_seconds); // Set expiration only if it's the first increment
  }
 
  if (current > limit) {
    throw new TRPCError({
      code: "TOO_MANY_REQUESTS",
      message: "You are being rate limited.",
    });
  }
 
  return next();
});

On this page