Load-Balancing Algorithms
Traefik Hub supports multiple load-balancing algorithms for distributing traffic across backend servers. Each algorithm suits different workload patterns — from basic even distribution to latency-aware routing and consistent hashing. This page covers what each algorithm does, when to use it, and how to configure it.
Weighted Round Robin (WRR)
WRR is the default algorithm. It distributes requests evenly across all servers in rotation, respecting server weights. Under the hood, it uses Earliest Deadline First (EDF) scheduling to achieve weighted distribution.
Assign a weight to each server to control how much traffic it receives relative to the others. A server with weight 3 receives three times the traffic of a server with weight 1.
- IngressRoute
- Routing Configuration
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`app.example.com`)
kind: Rule
services:
- name: my-app
port: 80
strategy: wrr
tls: {}
http:
services:
my-app:
loadBalancer:
strategy: wrr
servers:
- url: "http://10.0.0.1:80"
weight: 3
- url: "http://10.0.0.2:80"
weight: 1
When to use: Default choice for most workloads. Use weighted distribution during migrations to shift traffic gradually between backends.
Power of Two Choices (P2C)
P2C selects two servers at random and routes the request to the one with the fewest active connections. This is particularly effective in environments where backend servers have varying response times, as it naturally adapts to server load without requiring global state.
- IngressRoute
- Routing Configuration
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`app.example.com`)
kind: Rule
services:
- name: my-app
port: 80
strategy: p2c
tls: {}
http:
services:
my-app:
loadBalancer:
strategy: p2c
servers:
- url: "http://10.0.0.1:80"
- url: "http://10.0.0.2:80"
- url: "http://10.0.0.3:80"
When to use: Auto-scaling environments and workloads with variable connection lifetimes, such as WebSocket applications. P2C balances connections without the overhead of tracking global state.
Highest Random Weight (HRW)
HRW implements consistent hashing based on the client's source IP address. For each request, it computes a score for every available backend using a hash of the client IP combined with the backend identifier, then routes to the highest-scoring backend.
This provides implicit session affinity — requests from the same client consistently route to the same server — without requiring cookies.
- IngressRoute
- Routing Configuration
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`app.example.com`)
kind: Rule
services:
- name: my-app
port: 80
strategy: hrw
tls: {}
http:
services:
my-app:
loadBalancer:
strategy: hrw
servers:
- url: "http://10.0.0.1:80"
- url: "http://10.0.0.2:80"
- url: "http://10.0.0.3:80"
When to use: API clients, mobile apps, or sessionless connections where cookie-based stickiness isn't an option but you still need consistent routing. Also useful when backend servers maintain local caches that benefit from client affinity.
Least-Time
Least-Time selects servers based on the lowest average response time (Time To First Byte), combined with the fewest active connections, weighted by server capacity. The scoring formula is:
score = (avg_response_time × (1 + active_connections)) / weight
Ties are broken using WRR with EDF scheduling.
- IngressRoute
- Routing Configuration
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`app.example.com`)
kind: Rule
services:
- name: my-app
port: 80
strategy: leasttime
tls: {}
http:
services:
my-app:
loadBalancer:
strategy: leasttime
servers:
- url: "http://10.0.0.1:80"
weight: 3
- url: "http://10.0.0.2:80"
weight: 1
When to use: Latency-sensitive workloads where you want the gateway to automatically favor faster backends. Combines well with weighted distribution for mixed-capacity environments.
Sticky Sessions
Sticky sessions ensure that once a client is routed to a specific server, subsequent requests from the same client go to the same server.
Traefik sets a Set-Cookie header on the initial response, and the client returns it on subsequent requests.
- IngressRoute
- Routing Configuration
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`app.example.com`)
kind: Rule
services:
- name: my-app
port: 80
sticky:
cookie:
name: my_app_sticky
secure: true
httpOnly: true
sameSite: strict
tls: {}
http:
services:
my-app:
loadBalancer:
sticky:
cookie:
name: my_app_sticky
secure: true
httpOnly: true
sameSite: strict
servers:
- url: "http://10.0.0.1:80"
- url: "http://10.0.0.2:80"
Configuration Options
| Field | Description | Default | Required |
|---|---|---|---|
name | Cookie name. | SHA1 abbreviation (e.g., _1d52e) | No |
secure | Sets the Secure flag. | false | No |
httpOnly | Sets the HttpOnly flag. | false | No |
sameSite | Sets the SameSite attribute (strict, lax, none). | - | No |
maxAge | Cookie lifetime in seconds. 0 = session cookie, negative = expire immediately. | 0 | No |
domain | Cookie domain scope. | - | No |
path | Cookie path scope. | - | No |
If a sticky server becomes unhealthy, Traefik redirects traffic to a new healthy server and updates the cookie accordingly.
When to use: Stateful applications where the backend maintains session data locally. Combine with any algorithm — stickiness overrides the algorithm for returning clients. Note that combining sticky sessions with HRW is redundant: HRW already provides implicit stickiness via consistent hashing on the client IP, so both mechanisms will route to the same server anyway.
Health Checks
Health checks remove unhealthy servers from the load-balancing pool and re-add them when they recover. Traefik supports both active and passive checks.
Active Health Checks
Traefik periodically sends requests to a health endpoint on each server:
- IngressRoute
- Routing Configuration
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`app.example.com`)
kind: Rule
services:
- name: my-app
port: 80
healthCheck:
path: /health
interval: 10s
timeout: 3s
tls: {}
http:
services:
my-app:
loadBalancer:
healthCheck:
path: /health
interval: 10s
unhealthyInterval: 5s
timeout: 3s
status: 200
servers:
- url: "http://10.0.0.1:80"
- url: "http://10.0.0.2:80"
Configuration Options
| Field | Description | Default | Required |
|---|---|---|---|
path | Health check endpoint. | - | Yes |
interval | Check frequency for healthy targets. | 30s | No |
unhealthyInterval | Check frequency for unhealthy targets. | Same as interval | No |
timeout | Maximum wait for a response. | 5s | No |
status | Expected HTTP status code. | 2XX-3XX | No |
mode | Set to grpc for gRPC health check v1. | - | No |
headers | Custom headers to include in the check. | - | No |
followRedirects | Follow HTTP redirects. | true | No |
Passive Health Checks
Passive checks monitor real production traffic instead of sending synthetic requests:
- IngressRoute
- Routing Configuration
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: my-app
namespace: apps
spec:
entryPoints:
- websecure
routes:
- match: Host(`app.example.com`)
kind: Rule
services:
- name: my-app
port: 80
passiveHealthCheck:
failureWindow: 10s
maxFailedAttempts: 3
tls: {}
http:
services:
my-app:
loadBalancer:
passiveHealthCheck:
failureWindow: 10s
maxFailedAttempts: 3
servers:
- url: "http://10.0.0.1:80"
- url: "http://10.0.0.2:80"
Configuration Options
| Field | Description | Default | Required |
|---|---|---|---|
failureWindow | Time window for counting failures; also defines recovery duration. | 10s | No |
maxFailedAttempts | Consecutive failures before marking unhealthy. | 1 | No |
Combine active and passive health checks for the best coverage. Passive checks catch degradation in real traffic immediately, while active checks detect servers that are down but not receiving traffic.
Choosing an Algorithm
| Algorithm | Affinity | Adapts to Load | Scenario | Why It Fits |
|---|---|---|---|---|
| WRR (default) | No | No | Identical servers, uniform requests | Simple, predictable, no overhead |
| WRR with weights | No | No | Different server types/performance | Proportional to capacity |
| P2C | No | Yes (connections) | Auto-scaling, variable connection lifetimes | Balances connection count dynamically |
| HRW | Yes (IP-based) | No | Client affinity for caching, stateful backends | Consistent client-to-server mapping |
| Least-Time | No | Yes (latency + connections) | Heterogeneous backends, latency-sensitive | Optimizes for actual performance |
For cookie-based session affinity, add sticky sessions on top of any algorithm.
For service-level traffic management such as canary/blue-green deployments or traffic mirroring, see the related pages below.
Related Content
- Traffic Mirroring: Shadow testing with mirrored traffic
- A/B Testing: Weighted traffic splitting for comparison testing
- Canary Deployments: Progressive rollout strategies
- Services Reference: Complete service configuration options
- TraefikService Reference: Kubernetes CRD for WRR and mirroring
