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
Prerequisites
Before starting, ensure you have:[3]
- Existing NGINX Ingress Controller running
- Kubernetes cluster v1.22 or newer
-
kubectlconfigured 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
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
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
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"
Install Traefik:
helm upgrade --install traefik traefik/traefik \
--namespace traefik --create-namespace \
--values traefik-values.yaml
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 │
└─────────────────────────────────────────────────┘
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
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
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
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")
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")
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
Authorizationheaders 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
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
- Traefik NGINX Migration Guide[3]
- Traefik Gateway API Documentation[1]
- Kubernetes Gateway API Specification
- Traefik vs NGINX Comparison[5]
Top comments (0)