Rate Limiting

Token-bucket rate limiter for inbound WebSocket messages. Protects against spam, abuse, and runaway clients. Supports per-IP, per-connection, or custom key extraction, with optional auto-ban when a bucket is exhausted.

Different from throttle - throttle shapes outbound publish rate, rate limiting protects inbound against abuse.

Setup

// src/lib/server/ratelimit.js
import { createRateLimit } from 'svelte-adapter-uws/plugins/ratelimit';

export const limiter = createRateLimit({
  points: 10,         // 10 messages
  interval: 1000,     // per second
  blockDuration: 30000 // auto-ban for 30s when exhausted
});

Usage

// src/hooks.ws.js
import { limiter } from '$lib/server/ratelimit';

export function message(ws, { data, platform }) {
  const { allowed, remaining, resetMs } = limiter.consume(ws);
  if (!allowed) return; // drop the message

  // ... handle message normally
}

Options

OptionDefaultDescription
pointsrequiredTokens per interval (positive integer)
intervalrequiredRefill interval in ms
blockDuration0Auto-ban duration in ms when exhausted (0 = no auto-ban)
keyBy'ip''ip', 'connection', or (ws) → string

With keyBy: 'ip' (default), the limiter reads userData.remoteAddress, .ip, or .address. With keyBy: 'connection', each WebSocket gets its own bucket. Pass a function for custom grouping (e.g. by user ID or room).

API

MethodDescription
limiter.consume(ws, cost?)Deduct tokens (cost >= 0, defaults to 1). Returns { allowed, remaining, resetMs }
limiter.reset(key)Clear the bucket for a key
limiter.ban(key, duration?)Manually ban a key
limiter.unban(key)Remove a ban
limiter.clear()Reset all state

Limitations

  • Server-side only. No client component needed.
  • In-memory. Buckets live in the process. In cluster mode, each worker has independent rate limits (acceptable for most apps - abusers hit the same worker via the acceptor).
  • Lazy cleanup. Expired buckets are swept when the internal map exceeds 1000 entries.

Was this page helpful?