Gateway Architecture
The API Gateway is the single point of entry for all external traffic into the MATIH platform. Built on Kong 3.5.0 in DB-less (declarative) mode, it handles request routing, JWT authentication, tenant context injection, per-tenant rate limiting, and security filtering. Every request from a browser, CLI tool, or external API client passes through this gateway.
2.3.E.1Kong Configuration
| Parameter | Value | Rationale |
|---|---|---|
| Database mode | DB-less (declarative YAML) | GitOps-compatible, no external DB dependency |
| Proxy port | 8080 | Main traffic entry point |
| Admin port | 8444 (internal only) | Management API not exposed externally |
| Status port | 8100 | Health check endpoint for Kubernetes probes |
| Worker count | Auto (CPU cores) | NGINX worker processes |
| SSL termination | At load balancer / ingress | Gateway handles HTTP internally |
Why DB-less Mode
DB-less mode means Kong reads its entire configuration from a YAML file at startup. There is no PostgreSQL database for Kong itself (unlike the standard Kong deployment). This choice provides:
- Immutability -- Configuration is version-controlled alongside application code
- Reproducibility -- Every environment gets the exact same gateway configuration
- Speed -- No database dependency means faster startup (sub-second) and failover
- GitOps compatibility -- Configuration changes go through the same PR review process as code
- Reduced surface area -- No Kong admin API to secure against unauthorized changes
2.3.E.2Custom Lua Plugins
Three custom Lua plugins extend Kong's built-in functionality:
JWT Claims Extraction Plugin
Extracts tenant_id, user_id, and roles from the validated JWT and injects them as HTTP headers:
Incoming Request:
Authorization: Bearer eyJhbGci...
After Plugin:
Authorization: Bearer eyJhbGci... (preserved)
X-Tenant-ID: acme-corp (from JWT tenant_id claim)
X-User-ID: user-123 (from JWT sub claim)
X-User-Roles: data_analyst,viewer (from JWT roles claim)
X-Request-ID: req-abc-456 (generated if missing)
X-Correlation-ID: cor-def-789 (generated if missing)Tenant Rate Limiting Plugin
Enforces per-tenant rate limits stored in Redis:
| Tenant Tier | Requests/Min | Requests/Hour | Burst Limit |
|---|---|---|---|
| Free | 60 | 1,000 | 10 |
| Professional | 600 | 20,000 | 100 |
| Enterprise | 6,000 | 200,000 | 1,000 |
Rate counters use Redis sliding window: ratelimit:{tenant_id}:{window_start}.
When exceeded: 429 Too Many Requests with Retry-After header.
Request Validation Plugin
Input validation at the gateway edge:
| Check | Response on Failure |
|---|---|
| Content-Type on POST/PUT | 400 Bad Request |
| Content-Length within 10MB | 413 Payload Too Large |
Path traversal (../, %2e%2e) | 400 Bad Request |
| SQL injection patterns in query params | 400 Bad Request |
| Null bytes in URL or headers | 400 Bad Request |
| Authorization header on protected routes | 401 Unauthorized |
2.3.E.3Routing Table
Control Plane Routes
| Path Prefix | Upstream | Port | Auth |
|---|---|---|---|
/api/v1/auth/login | iam-service | 8081 | Public |
/api/v1/auth/register | iam-service | 8081 | Public |
/api/v1/auth/refresh | iam-service | 8081 | Refresh token |
/api/v1/auth/* | iam-service | 8081 | JWT |
/api/v1/users/* | iam-service | 8081 | JWT |
/api/v1/tenants/* | tenant-service | 8082 | JWT |
/api/v1/config/* | config-service | 8888 | JWT |
/api/v1/notifications/* | notification-service | 8085 | JWT |
/api/v1/audit/* | audit-service | 8086 | JWT |
/api/v1/billing/* | billing-service | 8087 | JWT |
/api/v1/observability/* | observability-api | 8088 | JWT |
/api/v1/infrastructure/* | infrastructure-service | 8089 | JWT |
/api/v1/registry/* | platform-registry | 8084 | JWT |
Data Plane Routes
| Path Prefix | Upstream | Port | Auth |
|---|---|---|---|
/api/v1/query/* | query-engine | 8080 | JWT |
/api/v1/catalog/* | catalog-service | 8086 | JWT |
/api/v1/semantic/* | semantic-layer | 8086 | JWT |
/api/v1/bi/* | bi-service | 8084 | JWT |
/api/v1/ai/* | ai-service | 8000 | JWT |
/api/v1/ai/chat/stream | ai-service | 8000 | JWT (SSE) |
/api/v1/ml/* | ml-service | 8000 | JWT |
/api/v1/pipelines/* | pipeline-service | 8092 | JWT |
/api/v1/quality/* | data-quality-service | 8000 | JWT |
/api/v1/ontology/* | ontology-service | 8101 | JWT |
/api/v1/governance/* | governance-service | 8080 | JWT |
/api/v1/render/* | render-service | 8098 | JWT |
2.3.E.4Streaming Support
Server-Sent Events (SSE)
Used by the AI service for streaming chat responses:
Client --> POST /api/v1/ai/chat/stream
Accept: text/event-stream
Gateway configuration:
- proxy_buffering: off
- proxy_read_timeout: 300s
- proxy_send_timeout: 300s
- keepalive_timeout: 300sWebSocket Upgrade
Used for real-time dashboard updates:
Client --> GET /api/v1/bi/ws
Connection: Upgrade
Upgrade: websocket
Gateway:
- Validates JWT before upgrade
- Upgrades connection to WebSocket
- Proxies frames bidirectionally
- Idle timeout: 300s2.3.E.5Gateway Metrics
Kong exports Prometheus metrics:
| Metric | Description |
|---|---|
kong_http_requests_total | Total requests by service, method, status |
kong_request_latency_ms | Gateway processing time |
kong_upstream_latency_ms | Upstream response time |
kong_bandwidth_bytes | Request/response bandwidth |
kong_rate_limiting_total | Rate limit hits by tenant |
Average gateway overhead: 2-5ms for authenticated requests, 1-2ms for public routes.
Related Sections
- Browser to Gateway -- Full request flow through the gateway
- Rate Limiting -- Per-tenant rate limiting details
- API Gateway Chapter -- Extended gateway documentation