Middleware
Rate limiting and timing middleware reference.
Rate Limiting
RateLimiter Interface
interface RateLimiter {
check(
key: string,
maxRequests: number,
windowSeconds: number,
): Promise<{ allowed: boolean; remaining: number }>;
}RedisRateLimiter
Redis-backed rate limiter using atomic INCR with TTL. Key format: ratelimit:{endpoint}:{clientKey}:{windowId}.
class RedisRateLimiter implements RateLimiter {
constructor(redis: RedisAdapter);
}Uses an atomic Lua script when the Redis client supports eval():
local c = redis.call('incr', KEYS[1])
if c == 1 then redis.call('expire', KEYS[1], ARGV[1]) end
return cFalls back to non-atomic INCR + SET for clients that do not support eval.
MemoryRateLimiter
In-memory sliding window limiter. Single-process only.
class MemoryRateLimiter implements RateLimiter {
constructor(sweepIntervalMs?: number); // Default: 60000
destroy(): void;
}Uses a Map<string, { count, resetAt }> with periodic sweep to remove expired entries. Call destroy() on shutdown to stop the sweep timer and allow the process to exit.
Rate Limit Middleware
Applied before JSON parsing and authorization. Returns null if the request is allowed, or a 429 response with Retry-After header if rate-limited.
function createRateLimitMiddleware(config: {
limiter: RateLimiter;
maxRequests: number;
windowSeconds: number;
endpoints?: Partial<Record<string, { maxRequests: number; windowSeconds: number }>>;
keyExtractor: (ctx: any) => string | Promise<string>;
}): (endpoint: string, ctx: any) => Promise<Response | null>;Execution Timing
ExecutionTimer
Tracks named execution phases sequentially.
class ExecutionTimer {
/** Start a named phase. Ends any in-progress phase. */
startPhase(name: string): void;
/** End the current phase. */
endPhase(): void;
/** Build the final timing event. */
build(endpoint: string, resource?: string, operation?: string): ExecutionTimingEvent;
}ExecutionTimingEvent
interface ExecutionTimingEvent {
endpoint: string;
resource?: string;
operation?: string;
phases: Record<string, number>; // phase name -> duration ms
totalMs: number;
timestamp: string; // ISO 8601
}TimingEmitter
Created from ObservabilityConfig. Returns null if timing is disabled (no runtime overhead). Custom onTiming handler errors are caught and logged.
function createTimingEmitter(config?: {
timing?: boolean;
onTiming?: (event: ExecutionTimingEvent) => void;
}, logger?: DatafnLogger): TimingEmitter | null;Usage in route handlers:
const timer = new ExecutionTimer();
timer.startPhase("validate");
// ... validation ...
timer.startPhase("execute");
// ... execution ...
const event = timer.build("query", "todos");
timingEmitter?.(event);