CAPABILITIES

Everything NovaGate can do today.

A complete feature reference for what is currently implemented and production-ready. No vaporware.

Routing & Proxying

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.

Authentication

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.

Rate Limiting

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).

Observability

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.

Config & Resilience

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.

Multi-Tenancy

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.