CAPABILITIES
A complete feature reference for what is currently implemented and production-ready. No vaporware.
Prefix path matching
Route /api/v1/* to specific downstream services with exact-prefix matching to prevent path collisions.
Per-service timeout
Configure request timeout per service (default 10s). Gateway returns 504 on breach without hanging connections.
X-Request-ID propagation
Auto-generates a UUID per request if absent. Forwarded to downstream and included in all logs and error responses.
X-Forwarded-For forwarding
Client IP chain is forwarded to downstream services for accurate IP attribution.
502 / 504 normalization
All downstream connection errors and timeouts are normalized to consistent JSON error bodies with error codes.
JWT Bearer validation
Validates RS256 / HS256 tokens on every request. Extracts sub, userId, or id claims into req.user.
TOKEN_EXPIRED vs TOKEN_INVALID
Distinct error codes so your frontend refresh interceptor can react correctly without false logouts.
Per-consumer API keys
Issue named API keys to each consumer. Keys are SHA-256 hashed at rest. Revocation takes effect instantly.
Auth-required per route
Mark individual routes as auth-required. Unauthenticated requests get 401 before reaching downstream.
Fail-open middleware
Missing Authorization header is allowed through. The route's authRequired flag decides whether to block.
Redis sliding window
ZSET-based sliding window — no thundering-herd at window boundaries unlike fixed-window implementations.
Two-tier limits
Separate limits for authenticated (500 req/min default) and unauthenticated (100 req/min default) clients.
Retry-After header
On 429, the gateway returns Retry-After with the exact number of seconds until the window resets.
Redis fail-open
If Redis is unreachable, the rate limiter allows the request and increments a Prometheus error counter — never blocks traffic.
Per-route override
Individual routes can override the global rate limit (e.g., tighter limits on /auth/login).
Prometheus metrics
http_requests_total, http_request_duration_ms (histogram), rate_limit_hits_total, downstream_timeout_total — all labeled by method, path, and status.
Buffered request logs
Every request generates a RequestLog entry. Flushed in batches of 100 or every 500ms to the control plane.
Error events
Gateway errors (5xx, timeouts) create ErrorEvent records with request ID, error code, and service ID for structured debugging.
Health snapshots
Gateway sends upstream service health data to the control plane on each health check cycle.
Dashboard log viewer
Filter logs by time range, path, status group, or consumer. Expandable rows show full request context.
Real-time WebSocket config push
Config changes from the dashboard propagate to your gateway over an authenticated WebSocket within milliseconds.
Offline resilience
If the control plane is unreachable, the gateway continues serving from in-memory config. Zero requests dropped on SaaS outages.
Redis warm-start cache
On gateway restart, config is loaded from local Redis (key: cfg:default) before the WebSocket connection is established.
Exponential reconnect backoff
WebSocket reconnects use 1s → 2s → 4s → 8s → 16s → 30s backoff. Permanent failures (4001, 4003, 4004) stop retrying.
Pending config queue
Config changes made while the gateway is offline are queued server-side and delivered on reconnect.
Schema-per-tenant isolation
Each tenant gets a dedicated PostgreSQL schema (tenant_<uuid>). No shared tables, no cross-tenant data leakage.
Instant tenant provisioning
New tenants are provisioned with a full schema, default tables, and an API key in one registration call.
Per-tenant config versioning
Every config change increments gatewayConfigVersion. The gateway acknowledges each version, ensuring no silent update loss.
Per-tenant observability
Logs, errors, metrics, and health data are scoped to the tenant. Tenants can only see their own traffic.