Skip to content
agentgateway has joined the Agentic AI FoundationLearn more

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Load balancing

Page as Markdown

Distribute requests across the endpoints of a backend with the Power of Two Choices (P2C) algorithm, for all traffic that the gateway proxies.

Distribute requests across the endpoints of a backend, for every kind of traffic that the gateway proxies.

About load balancing

Agentgateway load balances requests across the endpoints of a backend by using the Power of Two Choices (P2C) algorithm with health-aware scoring.

P2C applies to all traffic that the gateway proxies, not only to Large Language Model (LLM) traffic. Plain HTTP, gRPC, Model Context Protocol (MCP), and LLM backends share the same load balancer. The LLM load balancing guide applies the same algorithm across LLM providers.

For each request, agentgateway does the following:

  1. Selects two endpoints at random from the highest-priority locality bucket that has viable endpoints. The same endpoint can be selected twice, which keeps the lowest-scored endpoint reachable instead of starving it of traffic.
  2. Scores each of the two endpoints based on health, latency, and pending requests.
  3. Routes the request to the endpoint with the better score.

What the proxy load balances across

Whether agentgateway load balances across individual pods depends on how you reference the backend, not on the kind of traffic that you send.

Backend referenceWhat the proxy resolvesWhat makes the load balancing decision
A Kubernetes Service, such as an HTTPRoute backendRefs entry that points to a ServiceThe individual endpoints of the Service, from its EndpointSlicesAgentgateway, with P2C and health-aware scoring
A hostname or IP address, such as an AgentgatewayBackend that sets a host fieldOne opaque dial targetThe DNS resolver, or kube-proxy when the hostname resolves to a ClusterIP

By default when you route to a Kubernetes Service, agentgateway connects to a pod IP address directly, not to the ClusterIP, so kube-proxy does not make the load balancing decision.

Note

To load balance across the pod replicas of a self-hosted LLM backend, reference the Service instead of setting the host and port fields. For more information, see Load balancing across pod replicas.

How endpoints are scored

Agentgateway scores each endpoint on the following factors.

FactorDescription
HealthAn exponentially-weighted moving average (EWMA) of recent request outcomes. Each successful request records 1.0 and each failure records 0.0, with recent results weighted more heavily.
Request latencyAn EWMA of the upstream response time, in seconds. Only successful requests contribute, so that fast error responses do not skew the average.
Pending requestsThe number of in-flight requests to the endpoint. Each pending request adds a 10 percent penalty to the latency component.

The score for each endpoint is calculated as follows.

score = health / (1 + latency_penalty)
where latency_penalty = request_latency * (1 + pending_requests * 0.1)

Endpoints that consistently fail are moved to a rejected set and are considered only when no active endpoint is viable. As a result, traffic shifts away from a slow or failing pod without any configuration on your part.

Session affinity

P2C selects an endpoint independently for each request, so two requests from the same client can land on different endpoints. To send every request that carries the same value to the same endpoint, set the sessionAffinity backend policy.

A source CEL expression selects the value. Agentgateway hashes the value and maps the hash to an endpoint with weighted rendezvous hashing, so proxy replicas that see the same value and the same set of eligible endpoints pick the same endpoint without sharing any state with each other.

Set the policy on the AgentgatewayBackend that you route to.

apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
  name: my-backend
  namespace: agentgateway-system
spec:
  policies:
    sessionAffinity:
      source: request.headers["x-session-id"]

You can also set the policy in an AgentgatewayPolicy resource, in the spec.backend section, to apply it to a group of backends.

apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
metadata:
  name: my-affinity-policy
  namespace: agentgateway-system
spec:
  targetRefs:
  - group: agentgateway.dev
    kind: AgentgatewayBackend
    name: my-backend
  backend:
    sessionAffinity:
      source: request.headers["x-session-id"]
FieldRequiredDescription
sourceYesCEL expression evaluated against the request. It must return a string or bytes value. Requests that produce the same value are sent to the same healthy endpoint. The expression can be up to 16384 characters.

Common expressions for source include the following.

ExpressionAffinity per
request.headers["x-session-id"]Session identifier that the client sends.
string(source.address)Client IP address.
jwt.subAuthenticated user, when a JWT policy runs on the same route.

For the full list of values that an expression can read, see the CEL variables reference.

AI backends

On an AI backend, affinity applies across the provider groups of the backend. Set it on the whole AgentgatewayBackend, not on an individual provider. An AgentgatewayPolicy that sets backend.sessionAffinity and also names a sectionName on an AgentgatewayBackend target is rejected with the message backend.sessionAffinity must target the whole AgentgatewayBackend, not an individual AI provider. The rule applies to any sectioned AgentgatewayBackend target, not only to AI providers.

What session affinity does not do

Session affinity is best-effort, and it is not session persistence. Agentgateway does not record which endpoint a value was sent to. It recomputes the mapping for each request from the value and the set of healthy endpoints, which has two consequences.

  • The mapping moves when the endpoint set changes. Adding, removing, or losing an endpoint remaps some values, so a client can be moved to a different endpoint mid-session. Rendezvous hashing keeps that disruption small, because only the values that mapped to the changed endpoint move, but it is not zero.
  • A request that produces no usable value is not pinned. Agentgateway falls back to normal P2C selection when the expression fails to evaluate, returns a value that is not a string or bytes, or returns an empty value, such as a header that the client did not send. The request still succeeds.
  • Affinity does not override priority or health. The hash chooses among the endpoints that are already eligible, rather than reaching past them. Agentgateway works through the locality priority buckets in order and stops at the first bucket that holds a viable endpoint, and it considers the rejected set only when no active endpoint is viable anywhere. So two replicas in different localities can map the same value to different endpoints, and a value is remapped when the preferred bucket for a replica changes. For more information, see locality-aware routing.

Do not use session affinity to hold server-side state that only one endpoint has. Use it to improve cache hit rates, to keep a conversation on one replica when that is a preference rather than a requirement, or to make debugging easier.

Tip

A fallback is silent by design, so a misconfigured expression looks the same as working affinity from the outside. Each miss is logged at trace level with the expression and the reason, so run the proxy with trace logging when affinity does not appear to take effect.

Two other features choose an endpoint before affinity does, and they win when they apply: inference routing, and a stateful MCP session that is already pinned to an upstream server. In practice they do not conflict, because they target different backends.

Note

This policy is unrelated to MCP session routing, which controls whether agentgateway keeps an MCP session with the upstream server. Session affinity chooses an endpoint. MCP session routing chooses how the MCP protocol session is managed.

How load balancing interacts with other routing features

Endpoint selection is one stage of routing. The following features run before or instead of the P2C selection.

FeatureInteraction
Locality-aware routingEndpoints are grouped into priority buckets by locality. P2C selects within the highest-priority bucket that has viable endpoints.
Traffic splittingWeights choose which backend receives the request. P2C then chooses an endpoint within that backend.
Backend health checkingActive health checks remove an endpoint from the pool, in addition to the passive health scoring described above.

Verify which endpoints the proxy resolved

To confirm that the proxy resolved a Service to its endpoints, list the backends that the proxy is routing to.

agctl proxy config backends gateway/agentgateway-proxy -n agentgateway-system

The TYPE column tells you which case you are in. A Service row means that the proxy resolved the Kubernetes Service and load balances across its endpoints, one row per endpoint, named in the ENDPOINT column. A Backend row means an AgentgatewayBackend resource, which might be an opaque hostname.

TYPE     NAME       NAMESPACE            ENDPOINT                    HEALTH  REQUESTS  LATENCY
Backend  openai     agentgateway-system  backend                     0.70    1         0.00ms
Service  ext-authz  backend-extauth      ext-authz-7c7596b5f6-tvs28  1.00    4         0.00ms
Service  httpbin    backend-extauth      httpbin-7dc88b5fbc-zqrfn    1.00    2         3.06ms

Note

A service entry in the agctl proxy config all output means the same thing: the proxy is aware of the endpoints of the Service. It does not mean that the proxy routes to the ClusterIP of the Service.

For more information about these commands, including how to show services that have received no requests, see Inspect the proxy configuration.

Next steps

Was this page helpful?
Agentgateway assistant

Ask me anything about agentgateway configuration, features, or usage.

Note: AI-generated content might contain errors; please verify and test all returned information.

Tip: one topic per conversation gives the best results. Use the + button in the chat header to start a new conversation.

Switching topics? Starting a new conversation improves accuracy.
↑↓ navigate select esc dismiss

What could be improved?

Your feedback helps us improve assistant answers and identify docs gaps we should fix.

Need more help? Join us on Discord: https://discord.gg/y9efgEmppm

Want to use your own agent? Add the Solo MCP server to query our docs directly. Get started here: https://search.solo.io/.