Skip to content

Gateway Middlewares

1. Overview

Middlewares in Traefik process requests before they reach the backend service. BANA defines shared middlewares in packages/gateway/config/dynamic/middlewares.yml (file provider) and references them via Docker labels on each service with the @file suffix.

Source: packages/gateway/config/dynamic/middlewares.yml

2. Middleware Pipeline

3. Provider Namespacing

Traefik uses provider namespacing to distinguish where middlewares are defined:

SuffixProviderDefined In
@fileFile providerpackages/gateway/config/dynamic/middlewares.yml
@dockerDocker providerDocker labels on the service container
(none)Same providerOnly works within the same provider scope

Since shared middlewares live in the file provider, Docker labels must use the @file suffix:

yaml
# Correct
- "traefik.http.routers.commerce.middlewares=rate-limit@file,circuit-breaker@file,security-headers@file"

# Wrong — Traefik looks for "rate-limit" in Docker provider (doesn't exist)
- "traefik.http.routers.commerce.middlewares=rate-limit,circuit-breaker,security-headers"

4. Shared Middleware Definitions

All shared middlewares are defined in packages/gateway/config/dynamic/middlewares.yml.

Circuit Breaker

Trips when network error ratio exceeds 10% or P95 latency exceeds 3 seconds. After tripping, the circuit stays open for 15 seconds, then gradually recovers over 30 seconds. The 5xx-response-ratio term is present in source but commented out.

Source: packages/gateway/config/dynamic/middlewares.yml

yaml
http:
  middlewares:
    circuit-breaker:
      circuitBreaker:
        # 5xx-ratio term commented out in source:
        # expression: "ResponseCodeRatio(500, 600, 0, 600) > 0.30 || NetworkErrorRatio() > 0.10 || LatencyAtQuantileMS(95.0) > 3000"
        expression: "NetworkErrorRatio() > 0.10 || LatencyAtQuantileMS(95.0) > 3000"
        checkPeriod: 5s
        fallbackDuration: 15s
        recoveryDuration: 30s

States:

  • Closed — normal operation, requests pass through
  • Open — all requests fail fast with 503 (triggered by expression). Lasts fallbackDuration (15s).
  • Recovering — limited requests allowed to test recovery. Lasts up to recoveryDuration (30s). Returns to Closed if healthy, re-opens if expression still triggers.

Rate Limiting (Global)

Source: middlewares.yml (lines 53–59)

Applied to most services — 200 requests/second per client IP:

yaml
    rate-limit:
      rateLimit:
        average: 200
        burst: 400
        sourceCriterion:
          ipStrategy:
            depth: 1

Rate Limiting (Auth)

Source: middlewares.yml (lines 62–69)

Stricter limit for authentication endpoints — 30 requests/minute per client IP:

yaml
    rate-limit-auth:
      rateLimit:
        average: 30
        burst: 60
        period: 1m
        sourceCriterion:
          ipStrategy:
            depth: 1

sourceCriterion.ipStrategy.depth: 1 extracts the real client IP from the X-Forwarded-For header (required because Traefik sits behind Nginx).

Security Headers

Source: middlewares.yml (lines 72–79)

Hides server information and prevents common attacks:

yaml
    security-headers:
      headers:
        browserXssFilter: true
        contentTypeNosniff: true
        frameDeny: true
        customResponseHeaders:
          Server: ""
          X-Powered-By: ""
HeaderEffect
browserXssFilter: trueAdds X-XSS-Protection: 1; mode=block
contentTypeNosniff: trueAdds X-Content-Type-Options: nosniff
frameDeny: trueAdds X-Frame-Options: DENY
Server: ""Strips the Server response header
X-Powered-By: ""Strips the X-Powered-By response header

Dashboard Authentication

Source: middlewares.yml (lines 36–39)

The Traefik dashboard is protected by HTTP Basic Auth (not exposed with api.insecure):

yaml
    dashboard-auth:
      basicAuth:
        users:
          - "nx.eventry:$apr1$V3YHNLtR$x1jWCQ8.AiEfXoEc4ko7M0"

Redirect to Dashboard

Source: middlewares.yml (lines 30–34)

Redirects root path / to /dashboard/ on the traefik entrypoint:

yaml
    redirect-to-dashboard:
      redirectRegex:
        regex: "^/$"
        replacement: "/dashboard/"
        permanent: false

5. Dashboard Routers

Source: middlewares.yml (lines 8–23)

The dashboard is exposed via file provider routers on the traefik entrypoint (:8080 → host port 30100):

yaml
http:
  routers:
    dashboard:
      rule: "PathPrefix(`/api`) || PathPrefix(`/dashboard`)"
      entryPoints:
        - traefik
      service: api@internal
      middlewares:
        - dashboard-auth
    dashboard-redirect:
      rule: "Path(`/`)"
      entryPoints:
        - traefik
      service: api@internal
      middlewares:
        - redirect-to-dashboard
        - dashboard-auth
RouterRuleMiddlewaresNotes
dashboardPathPrefix(/api) || PathPrefix(/dashboard)dashboard-authMain dashboard + API routes
dashboard-redirectPath(/)redirect-to-dashboard, dashboard-authRoot redirect to /dashboard/

6. Applying Middlewares to Services

Middlewares are applied via Docker labels on each service. The @file suffix is required:

yaml
# Standard service (commerce, sale, finance, etc.)
labels:
  - "traefik.http.routers.commerce.middlewares=rate-limit@file,circuit-breaker@file,security-headers@file"

# Auth service (stricter rate limiting)
labels:
  - "traefik.http.routers.identity.middlewares=rate-limit-auth@file,circuit-breaker@file,security-headers@file"

7. Middleware Assignment per Service

ServiceRate LimitCircuit BreakerSecurity Headers
identityrate-limit-auth@file (30/min per-IP)YesYes
commercerate-limit@file (200/s per-IP)YesYes
salerate-limit@file (200/s per-IP)YesYes
financerate-limit@file (200/s per-IP)YesYes
inventoryrate-limit@file (200/s per-IP)YesYes
paymentrate-limit@file (200/s per-IP)YesYes
payment-webhooksecurity-headers@file
signal (REST)rate-limit@file (200/s per-IP)YesYes
signal (WS)
portal— (uses dashboard-auth@file for basic auth)

8. Adding Custom Middlewares

Option A: File provider (shared across services)

  1. Define the middleware in packages/gateway/config/dynamic/middlewares.yml
  2. Reference it in Docker labels with @file suffix:
    yaml
    - "traefik.http.routers.<service>.middlewares=<middleware-name>@file,..."
  3. Traefik auto-reloads file-based dynamic config (no restart needed)

Option B: Docker provider (per-service)

  1. Define the middleware directly in the service's Docker labels:
    yaml
    - "traefik.http.middlewares.<middleware-name>.<type>.<setting>=<value>"
  2. Reference it with @docker suffix (or no suffix from within Docker labels):
    yaml
    - "traefik.http.routers.<service>.middlewares=<middleware-name>@docker,..."

The payment webhook's replacepathregex middleware uses Option B since it is specific to that service.

DocumentDescription
Gateway OverviewIdentity card + service catalog
ArchitectureC4 views, request-routing flows
RoutingDocker label routing, 3 routing patterns
ResilienceCircuit breaker states, health checks, retry
ConfigurationTraefik/Nginx config, constants
DecisionsADRs

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.