Skip to main content

Free Tokens for Everyone | Runbook Live, Nov 19

Register
close

Retries, Timeouts, and Circuit Breaking in Kubernetes Without Code Changes

Linkerd Production Readiness Pre-Launch Checklist

Download Checklist

Oct 2026

TL;DR

  • HTTP and gRPC client libraries can apply different retry and timeout rules. You can keep behavior consistent across languages by setting policy in the mesh.
  • Buoyant's Linkerd enforces route-level retries and timeouts on meshed traffic through Kubernetes resources, without application code changes.
  • Linkerd configures per-endpoint circuit breaking through Service annotations. You should check the exact annotation and behavior against your Linkerd version.
  • Istio uses DestinationRule for outlier detection, while Cilium has a different set of layer-7 traffic controls. Compare the policies you need before choosing a mesh.

The polyglot reliability problem

Every HTTP or gRPC client library handles retries and timeouts differently, and circuit-breaker libraries add another set of settings. In a Kubernetes cluster with Go, Java, and Python services, those differences can make the same downstream failure spread in different ways.

During a partial outage, an HTTP client that retries each failed call 5 times can add load to a struggling pod. A gRPC client without a deadline can leave its caller waiting and tie up connections along the call chain. When each service owns its client settings, no single owner can change that behavior consistently during an incident.

Buoyant's Linkerd lets you put request policy in the platform layer, where proxies enforce it for meshed traffic regardless of application language. For example, you could set a deadline for checkout requests and permit retries only on operations you know are safe to repeat. The platform team can then change the policy without asking each service owner to ship a client-library update.

Best for: You run mixed-language services and want one owner for reliability behavior across meshed HTTP and gRPC calls.

What Linkerd enforces at the infrastructure layer

Buoyant’s Linkerd enforces reliability policy in the proxy beside each meshed workload. You can set retries and request timeouts on Gateway API HTTPRoute and GRPCRoute resources, while Service annotations configure circuit breaking for unhealthy endpoints. The proxy applies those rules independently of the application’s language.

For example, a platform engineer can put failure accrual on a Kubernetes Service so Linkerd stops sending requests to an endpoint after repeated failures. The annotation below shows the configuration surface. Check the value against your installed Linkerd version before applying it.

metadata:
  annotations:
    balancer.linkerd.io/failure-accrual: consecutive

ServiceProfile also defines route policy, but it’s the legacy configuration path. Linkerd applies the relevant policy to meshed HTTP and gRPC traffic. Requests that bypass the mesh don’t inherit it.

Best for Platform teams running mixed-language services that need consistent request behavior without maintaining a separate client-library configuration in every application.

Configuring retries and timeouts

A retry makes another attempt when a request meets a configured failure condition. A timeout sets a deadline for the request, so the proxy stops waiting for a response. Buoyant’s Linkerd applies these rules at the mesh layer, without changes to your HTTP or gRPC client code.

You can attach route-level policy to HTTPRoute or GRPCRoute resources. Pick the operation first. A read-only HTTP GET may tolerate a retry, but retrying a payment POST could create a duplicate charge. Keep the timeout bounded even on routes you choose not to retry.

Here’s a legacy ServiceProfile example for one HTTP route. Check the API version and field names against the Linkerd release you run before applying it.

apiVersion: linkerd.io/v1alpha2
kind: ServiceProfile
metadata:
  name: catalog.payments.svc.cluster.local
  namespace: payments
spec:
  routes:
    - name: GET /items
      condition:
        method: GET
        pathRegex: /items/.*
      isRetryable: true
      timeout: 2s

The example marks matching GET requests as retryable and gives them a 2-second timeout. Other routes don’t inherit that retry setting. For new HTTPRoute and GRPCRoute configurations, verify the supported API versions and the exact retry and timeout fields or annotations in your Linkerd documentation before translating this policy. Their configuration surface depends on the Linkerd release.

Best for: Use route timeouts when a slow dependency would hold up callers. Add retries only where another attempt can safely succeed and where the extra requests won’t worsen an overloaded backend.

Configuring circuit breaking

Circuit breaking stops sending requests to a failing endpoint before repeated failures pile up across a call chain. In Buoyant’s Linkerd, per-endpoint failure accrual tracks failed requests and temporarily removes an unhealthy pod from load balancing, so the proxy can send new requests to healthy pods.

Linkerd configures this behavior with a Kubernetes Service annotation, not a CRD. For a Service named payments, the platform team can add the annotation without changing the application.

kubectl annotate service payments \
  balancer.linkerd.io/failure-accrual=consecutive

Verify before applying: Check the annotation key, accepted value, and failure thresholds against the documentation for your installed Linkerd version. Failure accrual through this annotation does not apply when a ServiceProfile exists for the Service.

Best for services whose downstream pods fail intermittently, including shared clusters where one unhealthy pod can keep receiving traffic alongside healthy replicas. Apply the annotation through platform-managed Service configuration when you want the same policy across services.

A mixed HTTP/gRPC example

An HTTP frontend can call a gRPC catalog backend while Buoyant’s Linkerd proxies enforce route policy on both hops. In this example, frontend and catalog are existing Services. The HTTP route covers a read request, and the gRPC route covers the read RPC it calls.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: frontend-product-read
  annotations:
    retry.linkerd.io/http: "5xx"
    retry.linkerd.io/limit: "1"
    timeout.linkerd.io/request: "5s"
spec:
  parentRefs:
    - group: ""
      kind: Service
      name: frontend
      port: 8080
  rules:
    - matches:
        - method: GET
          path:
            type: Exact
            value: /products
      backendRefs:
        - name: frontend
          port: 8080
---
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: catalog-product-read
  annotations:
    retry.linkerd.io/grpc: "unavailable"
    retry.linkerd.io/limit: "1"
    timeout.linkerd.io/request: "5s"
spec:
  parentRefs:
    - group: ""
      kind: Service
      name: catalog
      port: 9090
  rules:
    - matches:
        - method:
            service: catalog.v1.Catalog
            method: GetProduct
      backendRefs:
        - name: catalog
          port: 9090
---
apiVersion: v1
kind: Service
metadata:
  name: catalog
  annotations:
    balancer.linkerd.io/failure-accrual: consecutive
spec:
  selector:
    app: catalog
  ports:
    - name: grpc
      port: 9090
      targetPort: 9090

The route annotations set retry conditions and request deadlines. The catalog Service annotation tells Linkerd to stop sending traffic to an endpoint after consecutive failures. Check the route API versions, annotation names, and retry-limit behavior against your installed Linkerd release before applying this YAML. Failure accrual also needs a separate check if catalog already has a ServiceProfile.

The 2 routes each permit a retry, so one frontend request could trigger repeated gRPC calls. Keep retries on read operations you know are safe to repeat, and test the combined attempt count under failure. Buoyant’s Linkerd proxies apply the configured behavior to meshed traffic regardless of the languages used by either service.

Best for: A platform team setting the same request rules for mixed-language HTTP and gRPC services without changing client libraries.

Why this is a platform policy, not a per-team opt-in

A platform policy gives one owner responsibility for how meshed services handle failures. If each service team chooses its own retry library and timeout, an incident responder has to reconstruct those choices before explaining why one call failed quickly and another kept waiting.

Buoyant's Linkerd lets you manage those choices alongside the per-route metrics, mTLS, and authorization policy your platform team already owns. For example, you can put a timeout on a checkout route and configure failure accrual on the downstream Service. You can then compare the route's latency and success rate with the behavior you intended. The platform team must apply those settings across the relevant routes and Services. Installing Linkerd alone doesn't create a cluster-wide reliability policy, and traffic outside the mesh won't inherit it.

Best for:You run mixed-language services under shared SLOs and want platform engineers to own the default behavior without asking every service team to add a library.

Linkerd vs Istio vs Cilium for reliability policy

Circuit breaking removes an unhealthy endpoint from a service’s available backends after repeated failures. The 3 meshes expose that behavior through different policy surfaces, which affects how you manage it alongside retries and timeouts.

Mesh Reliability policy Best for
Linkerd HTTPRoute and GRPCRoute define route-level retries and timeouts. A Service annotation enables per-endpoint failure accrual in the proxy. You want Kubernetes-managed policy across meshed HTTP and gRPC services.
Istio VirtualService defines retries and timeouts. DestinationRule sets outlier detection and connection-pool limits. Envoy enforces L7 policy through sidecars or, where supported, ambient waypoints. You need detailed traffic controls and already operate Istio’s policy model.
Cilium Cilium’s networking runs through eBPF. L7 reliability controls require traffic to pass through Envoy and may call for lower-level proxy configuration. You primarily want Cilium networking and can manage additional Envoy configuration where needed.

For example, a Linkerd Service can enable consecutive-failure accrual without a change to the application.

apiVersion: v1
kind: Service
metadata:
  name: catalog
  annotations:
    balancer.linkerd.io/failure-accrual: consecutive
spec:
  selector:
    app: catalog
  ports:
    - port: 80
      targetPort: 8080

Buoyant’s Linkerd keeps this circuit-breaking setting on the Service, while retry and timeout rules live on routes. The annotation’s behavior is version-specific, and failure accrual doesn’t apply when that Service has a ServiceProfile. Check your installed Linkerd version before rolling the policy across a cluster.

Conclusion

Platform teams standardizing reliability across mixed-language fleets should set a default for meshed services. Buoyant’s Linkerd lets you manage that behavior through Kubernetes configuration, so a Go service and a Java service don’t each need a separate client library policy. Start with services whose client behavior differs by language or owner.

FAQ

Do Linkerd retries and timeouts require application changes?

No. You configure route policy in Kubernetes, and Linkerd’s proxy enforces it for meshed requests. Choose retry conditions carefully for requests that change data.

Does the policy cover traffic outside the mesh?

No. Calls that bypass Linkerd’s proxy don’t inherit its retry, timeout, or circuit-breaking behavior.

Is Linkerd circuit breaking configured through a CRD?

Linkerd configures per-endpoint failure accrual through Service annotations. Check your Linkerd version’s annotation support and whether the Service has a ServiceProfile before applying it.

How does this differ from the gRPC retry-budget guide?

That separate guide covers limits on extra retry attempts for gRPC calls. Buoyant’s Linkerd policy here covers route-level reliability behavior for meshed HTTP and gRPC traffic.

When should you use route-level timeouts or retries?

Set a timeout when a request needs a deadline. Add retries only where another attempt can safely succeed, since retries can add load to a struggling service.