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
| Option | Default | Description |
|---|---|---|
points | required | Tokens per interval (positive integer) |
interval | required | Refill interval in ms |
blockDuration | 0 | Auto-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
| Method | Description |
|---|---|
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?