GH GambleHub

Plugins and middleware in the Gateway API

1) Why do you need plugins and middleware

API gateway - a point of enforcement of corporate policies. Correctly assembled plugin chain:
  • standardizes safety (authN/authZ, WAF, CORS),
  • protects stability (rate limit, circuit breaker, retry-policies),
  • manages the contract (validation of schemes, transformations),
  • gives observability (metrics, logs, tracing),
  • Reduces cost (caching, deduplication, canary rules)

Key: minimal latency and clear application consistency.

2) Plugin classes and what they do

1. Identification/Authentication

JWT/JWKS providers, OAuth2/OIDC, API keys, mTLS (client cert).
HMAC signatures (webhooks/partners), DPoP/PoP on the edge.

2. Authorization

RBAC/ABAC/OPA/Cedar (PDP) with local solution cache.
BOLA-guard: checking 'tenant '/' owner' in headers/context.

3. Network and protocol protection

WAF (OWASP CRS), anti-bots (rate/behavioral), Geo/IP/ASN filters, TLS profiles.
CORS, CSP headers, Fetch-Metadata filters, CORP/COOP/COEP.

4. Stability

Rate limiting (token bucket/GCRA), quotas and competitiveness.
Circuit breaker, timeouts, adaptive concurrency, load shedding.
Retry-policy with per-try timeout and jitter.

5. Transformations and validation

Path/Header Census, body-rewrite, JSON/XML ↔, gRPC ↔ HTTP.
Schema validation (OpenAPI/JSON Schema/Protobuf), ID normalization.

6. Caching and performance

Response/fragment cache, ETag/If-None-Match, compression, brotli.
Request collapsing (coalescing) for the same keys.

7. Observability and audit

RED/USE metrics, decision logging (429/403/5xx), tracing (W3C Trace-Context/OpenTelemetry), sampling (tail/adaptive).
Audit security headers and policy versions.

8. Life cycle and operation

Canary/blue-green, feature-flags, shadow solutions (log, not apply), version migrations.

3) Procedure of application (recommended chain)


[Ingress TLS]
→ Early-Deny (ASN/Geo, IP allow/deny)
→ mTLS / Client Cert Auth
→ JWT/OAuth2 AuthN (JWKS cache)
→ OPA/ABAC AuthZ (solution cache)
→ Rate Limit / Concurrency
→ Circuit / Timeout / Retries (пер-try)
→ Schema Validation (request)
→ Transform (headers/path/body) / CORS
→ Caching (lookup)
→ Upstream Proxy (app)
← Caching (store) / Compression
← Response Transform / Schema Validation (response)
← Logging / Tracing / Metrics / Security Headers

Principle: earlier - cheaper/more fatal (deny, auth, limits), later - "cosmetics" (transformation, cache).

4) Performance and cardinality

Stick to O (1) steps without external requests on the hot road.
All plugin "external calls" (PDP/JWKS) are via short TTL and asynchronous refresh.
Labels/labels for metrics - limited cardinality ('tenant', 'plan', 'route', but not 'user _ id').
"Heavy" plugins (WAF, body-transform) - enable selectively per-route.

5) Configuration examples

5. 1 Envoy: JWT + RateLimit + OPA + Retries (pseudo)

yaml static_resources:
listeners:
- name: public_listener filter_chains:
- filters:
- name: envoy. filters. network. http_connection_manager typed_config:
route_config:
name: main virtual_hosts:
- name: api domains: ["api. example. com"]
routes:
- match: { prefix: "/v1/payments" }
route:
cluster: payments timeout: 350ms retry_policy:
retry_on: connect-failure,reset,5xx,gateways num_retries: 1 per_try_timeout: 200ms http_filters:
- name: envoy. filters. http. jwt_authn typed_config:
providers:
oidc:
issuer: https://auth. example. com/
remote_jwks:
http_uri: { uri: https://auth. example. com/.well-known/jwks. json, cluster: jwks, timeout: 2s }
cache_duration: 300s forward: true
- name: envoy. filters. http. ext_authz  # OPA/Cedar PDP typed_config:
http_service:
server_uri: { uri: http://opa:8181, cluster: opa, timeout: 50ms }
authorization_request: { allowed_headers: { patterns: [{ exact: "authorization" }, { exact: "x-tenant" }] } }
- name: envoy. filters. http. ratelimit typed_config:
domain: public-api rate_limit_service:
grpc_service: { envoy_grpc: { cluster_name: rl } }
- name: envoy. filters. http. router

5. 2 NGINX/OpenResty: HMAC + Lua + Redis (pseudo)

nginx lua_shared_dict jwks 10m;
lua_shared_dict limits 10m;

server {
listen 443 ssl http2;

Early deny by ASN/Geo if ($bad_asn) { return 403; }

HMAC signature check (webhooks/partners)
set_by_lua_block $sig_ok {
return verify_hmac_signature(ngx. var. http_x_signature, ngx. var. request_time, ngx. var. request_body)
}
if ($sig_ok = 0) { return 401; }

Token bucket in Redis access_by_lua_block {
local key = ngx. var. binary_remote_addr.. ":".. ngx. var. request_uri local allowed, retry_after = ratelimit_allow(key, 50, 100)
if not allowed then ngx. header["Retry-After"] = retry_after return ngx. exit(429)
end
}

proxy_read_timeout 300ms;
proxy_connect_timeout 100ms;
proxy_pass http://app_backend;
}

5. 3 Kong: plugins along the route

yaml services:
- name: payments url: http://payments:8080 routes:
- service: payments paths: ["/v1/payments"]
plugins:
- name: jwt config: { key_claim_name: kid, secret_is_base64: false, run_on_preflight: false }
- name: opa config: { server_url: "http://opa:8181/v1/data/authz/allow", timeout: 50 }
- name: rate-limiting config: { second: 50, policy: redis, redis_host: redis, fault_tolerant: true }
- name: correlation-id config: { header_name: "traceparent" }
- name: response-transformer config: { add: { headers: ["Strict-Transport-Security:max-age=31536000"] } }

5. 4 Apache APISIX: JWT + Limit + Proxy-Mirror (shadow)

yaml routes:
- uri: /v1/wallets/
plugins:
openid-connect:
client_id: wallet discovery: "https://auth. example. com/.well-known/openid-configuration"
scope: "openid"
limit-count:
count: 100 time_window: 60 key_type: "var"
key: "remote_addr"
proxy-mirror:          # shadow traffic host: "http://shadow-backend:8080"
upstream_id: 1

5. 5 Traefik: Middleware chain

yaml http:
middlewares:
hsts-headers:
headers:
stsSeconds: 31536000 stsIncludeSubdomains: true ratelimit:
rateLimit:
average: 50 burst: 100 routers:
api:
rule: "Host(`api. example. com`) && PathPrefix(`/v1`)"
service: app middlewares:
- hsts-headers
- ratelimit

6) Multi-tenancy and policy versions

Routing key: '{tenant, plan, region, route, version}'.
Plugins read the'tenant' from the mTLS SAN/JWT stamp/header → apply limits/quotas/rules to the tenant.
Version policies ('policy _ version'), enter changelog and canary rollout.

7) Testing and rollout

Before release

Contract chain tests (if-then table): auth→deny, auth→allow, rate→429, schema→422.
Loading: bursts × 10, long plateaus, "dirty" patterns (slow-POST).
Chaos: PDP/JWKS/Redis degradation - must be fail-closed/degradation to minimum safe.

Release

'Report-Only '/shadow-mode (log solutions without application).
Canary 1-5% traffic + metric comparison (p95/p99, 4xx/5xx/429).
Automatic rollback on SLO/alerts.

8) Observability and metrics

Metrics:
  • `http_requests_total{route,tenant,plan,status}`
  • `request_duration_seconds_bucket{route}` (p95/p99)
  • `rate_limited_total{policy}`, `retry_total{reason}`, `circuit_state`
  • `authn_fail_total{reason}`, `authz_denied_total{action}`
  • `schema_validation_fail_total{route}`
  • Traces: spans per-filter, attributes' policy _ version ',' tenant ',' limit _ key '.
  • Logs (sampled): deny/429/5xx solutions with causes and 'trace _ id'.
  • Dashboards: Exec-summary, per-route, per-tenant, "hot" politicians.

9) Safety and operation

All secrets (HMAC, JWKS private, API keys) - in KMS/Vault, not in config files.
Deny-by-default policy for sensitive routes.
Short TTL JWKS/PDP cache, asynchronous updates with backoff.
Migration of transformation schemes - versioned; "breaking" - via dual-write.
Limit body-size (DoS) and JSON depth.

10) Antipatterns

A universal all-inclusive set of plugins on each route → extra milliseconds and bills.
External dependencies of plugins without cache/timeouts → cascading timeouts.
Lack of filter order: first transformation/logic, then limits - incorrect.
High cardinality of metric labels (raw 'user _ id '/' ip').
Mixing authN/authZ in transformation patterns (implicit solutions in Lua/Jinja).
Logging secrets/tokens.
One global Redis/cluster for all limits without shardiness/reserve.

11) Specifics of iGaming/Finance

Per tenant/per jurisdiction rules: KYC/AML, sanctions, limits of responsible payments.
Hard policies for payment routes: short timeouts, one repeat, idempotency ('Idempotency-Key').
Split perimeters for PSP/KYC SDK (separate domains/plugin chains).
Audit of unchangeable decision logs (conclusions, blocking, sanction refusal).

12) Prod Readiness Checklist

  • The filter order is authN → authZ → limits → circuit/timeout → schema → transform → cache.
  • Per-route set of plugins; heavy - only where necessary.
  • JWKS/PDP with short TTL and cache; timeouts and fallback strategies.
  • Rate/Quota/Concurrency - keys are designed, storage sharding.
  • RED/USE metric set, OTel tracing, tail/adaptive sampling.
  • Canary + shadow mode, auto-rollback by SLO.
  • Secrets in KMS/Vault; configs - versioned, with migrations.
  • Body/headers limits; oversize/slow-POST protection.
  • Customer documentation: codes 401/403/409/422/429/5xx, 'Retry-After', example headers.

13) TL; DR

Build an "early failure → authentication/authorization → limits/persistence → → transformation validation/cache → telemetry" chain. Enable only the necessary plugins per-route, cache external solutions (JWKS/PDP), set timeouts and retry policies, control the cardinality of metrics. Release via shadow/canary, keep secrets in KMS/Vault and measure the impact of each plugin on p95/p99.

Contact

Get in Touch

Reach out with any questions or support needs.We are always ready to help!

Start Integration

Email is required. Telegram or WhatsApp — optional.

Your Name optional
Email optional
Subject optional
Message optional
Telegram optional
@
If you include Telegram — we will reply there as well, in addition to Email.
WhatsApp optional
Format: +country code and number (e.g., +380XXXXXXXXX).

By clicking this button, you agree to data processing.