gRPC automatic retry and hedging config
gRPC clients can retry failed RPCs automatically when the service config JSON declares a retryPolicy or hedgingPolicy under a method’s methodConfig entry. This reference lists every field in both policies with its JSON type, whether it is required, and what it controls, plus a live search.
retryPolicy: sequential retries with exponential backoff
A retryPolicy retries sequentially: attempt 1 fails, the client waits a backoff interval, then attempt 2 runs, and so on up to maxAttempts. The wait grows exponentially with jitter:
"retryPolicy": {
"maxAttempts": 4,
"initialBackoff": "0.1s",
"maxBackoff": "1s",
"backoffMultiplier": 2,
"retryableStatusCodes": ["UNAVAILABLE", "RESOURCE_EXHAUSTED"]
}
With this config, the original call is attempt 1. If it fails with UNAVAILABLE, the client waits a random time in [0, 0.1s), then tries again. If attempt 2 also fails, it waits in [0, 0.2s) (multiplied by 2), capped at 1s. Attempt 3 follows, then the final attempt 4, after which the RPC fails to the caller.
Important: maxAttempts counts the original call as attempt 1, not as attempt 0. So maxAttempts: 4 allows up to 3 retries after the first failure.
hedgingPolicy: parallel in-flight attempts
A hedgingPolicy takes a different approach: it fires a new attempt every hedgingDelay without waiting for the previous one to fail, and uses whichever responds successfully first. Subsequent responses are cancelled:
"hedgingPolicy": {
"maxAttempts": 3,
"hedgingDelay": "0.5s",
"nonFatalStatusCodes": ["UNAVAILABLE"]
}
The original call fires at t=0. At t=0.5s a second attempt fires (whether or not the first has responded). At t=1.0s a third fires. The first successful response wins. This trades server load for reduced tail latency — useful for read-only RPCs against high-percentile latency spikes.
A method may configure retryPolicy or hedgingPolicy, never both. They represent fundamentally different strategies and the gRPC spec forbids combining them on the same method.
Choosing safe status codes
Not every failure is safe to retry. The key question is whether retrying the call is idempotent — can you safely issue the same RPC twice without side effects?
UNAVAILABLE— almost always safe; the server was unreachable, so no mutation could have occurred.RESOURCE_EXHAUSTED— safe for quota-limited reads; use with care for writes.DEADLINE_EXCEEDED— risky for writes. The server may have processed the request before the deadline; retrying could cause a duplicate mutation.ABORTED— safe only if your server documents it as a retry-safe signal (e.g., Spanner uses it for optimistic concurrency).
Avoid listing INTERNAL or UNKNOWN as retryable — those often indicate non-transient bugs.
retryThrottling: channel-level protection
Individual method policies are bounded by the channel’s retryThrottling setting. If retry attempts across all methods on a channel exceed the throttle ratio, the client stops retrying and fails fast, preventing a cascade where many simultaneous failures generate a retry storm. Set retryThrottling in the channel’s service config at the top level, separate from methodConfig.
Tips and notes
- Duration values are strings with an
ssuffix, e.g."0.5s"or"1.5s". Milliseconds must be written as"0.5s"not"500ms". - Omitting
retryableStatusCodesentirely disables retry even if aretryPolicyblock is present — only failures matching listed codes are retried. - The search field on this page filters by field name and status code, useful when confirming the exact JSON key spelling before pasting into your service config.