DEV Community

DEV-AI
DEV-AI

Posted on

Inter-Service API communication with Caching in Kubernetes: Migration from NGINX Ingress to Traefik Gateway API

In modern Kubernetes microservices architectures, services frequently communicate with each other using internal REST APIs through service discovery. While this pattern works well, it creates significant performance challenges when multiple pod replicas make identical requests simultaneously to backends that serve infrequently-changing data.[1]

Real-World Scenario

Consider an e-commerce platform where:

  • A frontend service calls catalog-service.svc.cluster.local:8080/products?category=electronics
  • The catalog service queries inventory-service.svc.cluster.local:8080/stock?productId=12345
  • Multiple pod replicas make identical requests simultaneously
  • Product catalog data changes infrequently but gets fetched thousands of times per minute

The cost: Unnecessary database queries, increased latency, and wasted compute resources.

Why Traditional Solutions Fall Short

Most caching solutions focus on external traffic (north-south), but internal service-to-service communication (east-west) is equally critical. Traditional approaches have limitations:[2]

  • Application-level caching requires code changes in every service
  • NGINX Ingress controllers only handle external traffic, not internal cluster calls
  • Service meshes add operational complexity and resource overhead

Additionally, NGINX Ingress Controller has announced its retirement in March 2026, with no new releases, security patches, or bug fixes after this date. Organizations must migrate to future-proof alternatives.[3][1]

The Solution: Traefik with Kubernetes Gateway API

The Kubernetes community has standardized on the Gateway API as the long-term replacement for Ingress. Traefik fully supports Gateway API v1.3.0 with advanced routing capabilities and caching middleware, making it an ideal replacement for NGINX Ingress while adding sophisticated caching features.[4][1]

Why Gateway API?

Gateway API provides:[1]

  • Role-oriented design: Separates infrastructure (GatewayClass) from application routing (HTTPRoute)
  • Expressive routing: Support for header matching, path rewriting, and query parameters
  • Extensibility: Native support for middleware and filters
  • Future-proof: Official Kubernetes standard replacing Ingress

Why Traefik Over NGINX?

Traefik offers significant advantages over NGINX Ingress:[5][4][2]

  • Native Gateway API support: One of the first controllers to fully implement Gateway API
  • Zero-downtime migration: Automatic translation of NGINX annotations to Traefik configuration
  • Lightweight architecture: Lower resource consumption in dynamic environments
  • Built-in features: Let's Encrypt, Prometheus metrics, and dashboard included
  • Dynamic configuration: Automatic service discovery without restarts

Migration Strategy: NGINX Ingress to Traefik

Migration Overview

The migration achieves zero downtime by running Traefik alongside NGINX, with both controllers serving the same Ingress resources simultaneously. This allows progressive traffic shifting before removing NGINX.[3]

Current:  DNS → LoadBalancer → NGINX → Your Services
Migration: DNS → LoadBalancer → NGINX → Your Services
                → LoadBalancer → Traefik → Your Services
Final:    DNS → LoadBalancer → Traefik → Your Services
Enter fullscreen mode Exit fullscreen mode

Prerequisites

Before starting, ensure you have:[3]

  • Existing NGINX Ingress Controller running
  • Kubernetes cluster v1.22 or newer
  • kubectl configured with cluster admin permissions
  • Helm 3.9+
  • Cluster support for multiple LoadBalancer services on ports 80/443
  • Backup of critical configurations

Backup your configurations:

# Export all Ingress resources
kubectl get ingress --all-namespaces -o yaml > ingress-backup.yaml

# Export NGINX ConfigMaps
kubectl get configmap --all-namespaces -l app.kubernetes.io/name=ingress-nginx -o yaml > nginx-configmaps.yaml
Enter fullscreen mode Exit fullscreen mode

Step 1: Install Gateway API CRDs

# Install Gateway API v1.3.0 CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml

# Install Traefik RBAC for Gateway API
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.5/docs/content/reference/dynamic-configuration/kubernetes-gateway-rbac.yml
Enter fullscreen mode Exit fullscreen mode

Step 2: Install Traefik Alongside NGINX

Install Traefik with both Gateway API and NGINX Ingress compatibility enabled:[4][3]

# Add Traefik Helm repository
helm repo add traefik https://traefik.github.io/charts
helm repo update

# Create namespace
kubectl create namespace traefik
Enter fullscreen mode Exit fullscreen mode

Create traefik-values.yaml:

providers:
  # Enable Gateway API provider
  kubernetesGateway:
    enabled: true
    namespacePolicy: All
  # Enable NGINX Ingress compatibility for migration
  kubernetesIngressNginx:
    enabled: true
    publishService:
      enabled: false  # Prevent competing DNS updates

deployment:
  replicas: 2

logs:
  access:
    enabled: true
    format: json

# Enable dashboard for debugging
ingressRoute:
  dashboard:
    enabled: true
    matchRule: Host(`traefik.localhost`)
    entryPoints:
      - web

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "2Gi"
    cpu: "1000m"
Enter fullscreen mode Exit fullscreen mode

Install Traefik:

helm upgrade --install traefik traefik/traefik \
  --namespace traefik --create-namespace \
  --values traefik-values.yaml
Enter fullscreen mode Exit fullscreen mode

Implementation Architecture: Adding Caching

Now that you've migrated to Traefik, implement intelligent HTTP caching for internal service communication.

Component Overview

┌─────────────────────────────────────────────────┐
│          Frontend Service Pod                   │
│ HTTP GET /products?category=electronics         │
└─────────────────┬───────────────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────────────┐
│         Traefik Gateway (Internal)              │
│  ┌──────────────────────────────────────────┐   │
│  │       HTTP Cache Middleware              │   │
│  │  - Cache Key: URL + Query Params         │   │
│  │  - TTL: 300s                             │   │
│  │  - Memory Store: 2Gi                     │   │
│  └──────────────────────────────────────────┘   │
└─────────────────┬───────────────────────────────┘
                  │ (Cache Miss)
                  ▼
┌─────────────────────────────────────────────────┐
│         Catalog Service Backend                 │
│      catalog-service.default:8080               │
└─────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Step 7: Create Internal Gateway and GatewayClass

Define the infrastructure layer for internal service communication:[1]

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: traefik-internal
spec:
  controllerName: traefik.io/gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: internal-api-gateway
  namespace: traefik
spec:
  gatewayClassName: traefik-internal
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: All
Enter fullscreen mode Exit fullscreen mode

Step 8: Configure HTTP Cache Middleware

Create cache middleware for different caching strategies:

# Short TTL for frequently changing data
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: cache-30s
  namespace: traefik
spec:
  plugin:
    cache:
      path: /var/cache/traefik
      maxExpiry: 30
      cacheQueryParams: true
      addStatusHeader: true
      blacklistedHeaders:
        - Authorization
---
# Long TTL for static data
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: cache-5m
  namespace: traefik
spec:
  plugin:
    cache:
      path: /var/cache/traefik
      maxExpiry: 300
      cacheQueryParams: true
      addStatusHeader: true
      blacklistedHeaders:
        - Authorization
Enter fullscreen mode Exit fullscreen mode

Step 9: Create HTTPRoute with Caching

Define application routing with cache middleware:[1]

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: catalog-api-route
  namespace: default
spec:
  parentRefs:
    - name: internal-api-gateway
      namespace: traefik
  # Internal hostname for cluster access
  hostnames:
    - "catalog-api.cluster.local"
  rules:
    # Stock levels - short cache
    - matches:
        - path:
            type: PathPrefix
            value: /stock
          method: GET
      filters:
        - type: ExtensionRef
          extensionRef:
            group: traefik.io
            kind: Middleware
            name: cache-30s
      backendRefs:
        - name: inventory-service
          port: 8080

    # Product catalog - long cache
    - matches:
        - path:
            type: PathPrefix
            value: /products
          method: GET
      filters:
        - type: ExtensionRef
          extensionRef:
            group: traefik.io
            kind: Middleware
            name: cache-5m
      backendRefs:
        - name: catalog-service
          port: 8080

    # Don't cache mutations
    - matches:
        - path:
            type: PathPrefix
            value: /products
          method: POST
      backendRefs:
        - name: catalog-service
          port: 8080
Enter fullscreen mode Exit fullscreen mode

Step 10: Update Service Clients

Update your service clients to use the Gateway hostname:

Before (Direct Service Call):

resp, err := http.Get("http://catalog-service.default.svc.cluster.local:8080/products")
Enter fullscreen mode Exit fullscreen mode

After (Via Traefik Gateway with Caching):

resp, err := http.Get("http://traefik.traefik.svc.cluster.local/products")
// Or use custom internal DNS
resp, err := http.Get("http://catalog-api.cluster.local/products")
Enter fullscreen mode Exit fullscreen mode

Monitoring and Performance

Cache Hit Rate Metrics

The middleware adds an X-Cache-Status header to responses:

  • HIT: Response served from cache
  • MISS: Response fetched from backend
  • BYPASS: Request not cacheable

Expected Performance Impact

Based on typical microservices patterns:[2]

Metric Without Cache With Cache Improvement
Average Latency 45ms 3ms 93% reduction
Backend Load 10,000 req/s 2,000 req/s 80% reduction
Database Queries 8,000/s 1,600/s 80% reduction
P99 Latency 250ms 15ms 94% reduction

Best Practices

Cache Configuration

  • Only cache idempotent GET requests for data that changes infrequently
  • Set appropriate TTLs based on your data volatility
  • Allocate cache memory based on traffic patterns: (Avg Response Size × Cache Hit Rate × RPS × TTL) ÷ Replicas

Security Considerations

  • Exclude Authorization headers from cache keys
  • Don't cache user-specific or authenticated requests
  • Use ReferenceGrants for cross-namespace secret access[1]

High Availability

Configure multiple replicas with pod anti-affinity:[3]

deployment:
  replicas: 2
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchLabels:
              app.kubernetes.io/name: traefik
          topologyKey: kubernetes.io/hostname
podDisruptionBudget:
  enabled: true
  minAvailable: 1
Enter fullscreen mode Exit fullscreen mode

Conclusion

Migrating from NGINX Ingress to Traefik with Gateway API and implementing intelligent HTTP caching provides:

Future-proof architecture using Kubernetes Gateway API standard[1]
Zero-downtime migration from retiring NGINX Ingress[4][3]
Significant performance improvements (80-95% latency reduction)[2]
Reduced backend load and database pressure

Zero application code changes required

Fine-grained control over caching policies

With NGINX Ingress reaching end-of-life in March 2026, adopting Traefik with Gateway API ensures your cluster stays aligned with Kubernetes' networking future while adding powerful caching capabilities for internal service communication.[1][3]

Resources


Top comments (0)