From f8a754cc312b20308941a64210795ff138e13c12 Mon Sep 17 00:00:00 2001 From: AgraVator Date: Sat, 1 Aug 2026 19:48:52 +0530 Subject: [PATCH 1/8] A50 update: exclude locally-initiated client cancellations from call counter --- A50-xds-outlier-detection.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/A50-xds-outlier-detection.md b/A50-xds-outlier-detection.md index a58bf319c..692a2ce4e 100644 --- a/A50-xds-outlier-detection.md +++ b/A50-xds-outlier-detection.md @@ -137,7 +137,7 @@ When the `outlier_detection` LB policy receives an address update, it will creat When the child policy asks for a subchannel, the `outlier_detection` will wrap the subchannel with a wrapper (see [Subchannel Wrapper section](#subchannel-wrapper)). Then, the subchannel wrapper will be added to the list in the map entry for its address, if that map entry exists. If there is no map entry, or if the subchannel is created with multiple addresses, the subchannel will be ignored for outlier detection. If that address is currently ejected, that subchannel wrapper's `eject` method will be called. -The `outlier_detection` LB policy will provide a picker that delegates to the child policy's picker, and when the request finishes, increment the corresponding counter in the map entry referenced by the subchannel wrapper that was picked. If both the `success_rate_ejection` and `failure_percentage_ejection` fields are unset in the configuration, the picker should not do that counting. +The `outlier_detection` LB policy will provide a picker that delegates to the child policy's picker, and when the request finishes, increment the corresponding counter in the map entry referenced by the subchannel wrapper that was picked. Locally-initiated client-side cancellations (`hedging cancellations`, `application CANCELLED`, and `DEADLINE_EXCEEDED`) MUST be excluded from `successCount` and `failureCount`. If both the `success_rate_ejection` and `failure_percentage_ejection` fields are unset in the configuration, the picker should not do that counting. The `outlier_detection` LB policy will have a timer that triggers on a period determined by the `interval` config option, and does the following: @@ -170,7 +170,7 @@ To un-eject an address, set the current ejection timestamp to `null` and call `u ### Call Counter -This design is based directly on Envoy's implementation. The object contains two buckets, and each bucket has a number counting successes, and another counting failures. The active bucket is updated each time a call finishes. When the timer triggers, the inactive bucket is zeroed and swapped with the active bucket. Then the inactive bucket contains the number of successes and failures since the last time the timer triggered. Those numbers are used to evaluate the ejection criteria. +This design is based directly on Envoy's implementation. The object contains two buckets, and each bucket has a number counting successes (`successCount`), and another counting failures (`failureCount`). The active bucket is updated each time a call finishes, excluding locally-initiated client-side cancellations (`hedging cancellations`, `application CANCELLED`, and `DEADLINE_EXCEEDED`). When the timer triggers, the inactive bucket is zeroed and swapped with the active bucket. Then the inactive bucket contains the number of successes and failures since the last time the timer triggered. Those numbers are used to evaluate the ejection criteria. ### Subchannel Wrapper @@ -282,6 +282,10 @@ Envoy's specification of outlier detection includes the ejection criteria Consec Envoy defines some errors as "external" and some as "local origin", and their specification of outlier detection allows separate configurations for handling each of them. gRPC does not separate errors that way, so there is no way to split them like that and handle those two categories separately. +### Excluding Locally-Initiated Client-Side Cancellations + +Locally-initiated client-side cancellations (`hedging cancellations`, `application CANCELLED`, and `DEADLINE_EXCEEDED`) are excluded from outlier detection counting (`successCount` and `failureCount`). This aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. + ### Map Entry Source We chose to populate the map entries using the address list passed in from the parent LB policy. As an alternative, we considered populating the map using addresses that the child LB policy uses to create subchannels. These two options would have approximately the same behavior with all common child LB policies, and this choice simplifies management of the lifecycle of map entries. From 11fbd2f5df52950e7e1e92d9fbbea103fd2c4743 Mon Sep 17 00:00:00 2001 From: AgraVator Date: Sat, 1 Aug 2026 19:56:20 +0530 Subject: [PATCH 2/8] A50 update: include DEADLINE_EXCEEDED in excluded client-side cancellations --- A50-xds-outlier-detection.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/A50-xds-outlier-detection.md b/A50-xds-outlier-detection.md index 692a2ce4e..f34ea73a2 100644 --- a/A50-xds-outlier-detection.md +++ b/A50-xds-outlier-detection.md @@ -137,7 +137,7 @@ When the `outlier_detection` LB policy receives an address update, it will creat When the child policy asks for a subchannel, the `outlier_detection` will wrap the subchannel with a wrapper (see [Subchannel Wrapper section](#subchannel-wrapper)). Then, the subchannel wrapper will be added to the list in the map entry for its address, if that map entry exists. If there is no map entry, or if the subchannel is created with multiple addresses, the subchannel will be ignored for outlier detection. If that address is currently ejected, that subchannel wrapper's `eject` method will be called. -The `outlier_detection` LB policy will provide a picker that delegates to the child policy's picker, and when the request finishes, increment the corresponding counter in the map entry referenced by the subchannel wrapper that was picked. Locally-initiated client-side cancellations (`hedging cancellations`, `application CANCELLED`, and `DEADLINE_EXCEEDED`) MUST be excluded from `successCount` and `failureCount`. If both the `success_rate_ejection` and `failure_percentage_ejection` fields are unset in the configuration, the picker should not do that counting. +The `outlier_detection` LB policy will provide a picker that delegates to the child policy's picker, and when the request finishes, increment the corresponding counter in the map entry referenced by the subchannel wrapper that was picked. Locally-initiated client-side cancellations (`hedging cancellations`, application `CANCELLED`, and `DEADLINE_EXCEEDED`) MUST be excluded from `successCount` and `failureCount`. If both the `success_rate_ejection` and `failure_percentage_ejection` fields are unset in the configuration, the picker should not do that counting. The `outlier_detection` LB policy will have a timer that triggers on a period determined by the `interval` config option, and does the following: @@ -170,7 +170,7 @@ To un-eject an address, set the current ejection timestamp to `null` and call `u ### Call Counter -This design is based directly on Envoy's implementation. The object contains two buckets, and each bucket has a number counting successes (`successCount`), and another counting failures (`failureCount`). The active bucket is updated each time a call finishes, excluding locally-initiated client-side cancellations (`hedging cancellations`, `application CANCELLED`, and `DEADLINE_EXCEEDED`). When the timer triggers, the inactive bucket is zeroed and swapped with the active bucket. Then the inactive bucket contains the number of successes and failures since the last time the timer triggered. Those numbers are used to evaluate the ejection criteria. +This design is based directly on Envoy's implementation. The object contains two buckets, and each bucket has a number counting successes (`successCount`), and another counting failures (`failureCount`). The active bucket is updated each time a call finishes, excluding locally-initiated client-side cancellations (`hedging cancellations`, application `CANCELLED`, and `DEADLINE_EXCEEDED`). When the timer triggers, the inactive bucket is zeroed and swapped with the active bucket. Then the inactive bucket contains the number of successes and failures since the last time the timer triggered. Those numbers are used to evaluate the ejection criteria. ### Subchannel Wrapper @@ -284,7 +284,7 @@ Envoy defines some errors as "external" and some as "local origin", and their sp ### Excluding Locally-Initiated Client-Side Cancellations -Locally-initiated client-side cancellations (`hedging cancellations`, `application CANCELLED`, and `DEADLINE_EXCEEDED`) are excluded from outlier detection counting (`successCount` and `failureCount`). This aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. +Locally-initiated client-side cancellations (`hedging cancellations`, application `CANCELLED`, and `DEADLINE_EXCEEDED`) are excluded from outlier detection counting (`successCount` and `failureCount`). Although `DEADLINE_EXCEEDED` could be argued as an endpoint or network issue, implementation-wise it is treated as a client-side cancellation. This aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. ### Map Entry Source From 0ec0d2c61532cfb55c8ece3dc0be04a159acdaa6 Mon Sep 17 00:00:00 2001 From: AgraVator Date: Mon, 3 Aug 2026 12:28:26 +0530 Subject: [PATCH 3/8] A50 update: clarify Envoy resetStream vs DEADLINE_EXCEEDED semantics in rationale --- A50-xds-outlier-detection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/A50-xds-outlier-detection.md b/A50-xds-outlier-detection.md index f34ea73a2..bb66f388d 100644 --- a/A50-xds-outlier-detection.md +++ b/A50-xds-outlier-detection.md @@ -284,7 +284,7 @@ Envoy defines some errors as "external" and some as "local origin", and their sp ### Excluding Locally-Initiated Client-Side Cancellations -Locally-initiated client-side cancellations (`hedging cancellations`, application `CANCELLED`, and `DEADLINE_EXCEEDED`) are excluded from outlier detection counting (`successCount` and `failureCount`). Although `DEADLINE_EXCEEDED` could be argued as an endpoint or network issue, implementation-wise it is treated as a client-side cancellation. This aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. +Locally-initiated client-side cancellations (`hedging cancellations`, application `CANCELLED`, and `DEADLINE_EXCEEDED`) are excluded from outlier detection counting (`successCount` and `failureCount`). For locally-initiated cancellations (`hedging cancellations` of non-winning sibling attempts and application-initiated cancellations), this aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. For `DEADLINE_EXCEEDED`, this differs from Envoy (which counts deadline expirations as failures for outlier detection); however, because deadline expiration semantics vary between Envoy and gRPC, and implementation-wise it is much simpler to handle `DEADLINE_EXCEEDED` identically to cancellation, gRPC treats it as a client-side cancellation. ### Map Entry Source From b027e8d3fc7444b858a8c01e800ef51fbd2cc777 Mon Sep 17 00:00:00 2001 From: AgraVator Date: Mon, 3 Aug 2026 12:32:13 +0530 Subject: [PATCH 4/8] A50 update: use first-principles argument for DEADLINE_EXCEEDED in rationale --- A50-xds-outlier-detection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/A50-xds-outlier-detection.md b/A50-xds-outlier-detection.md index bb66f388d..c74f9c632 100644 --- a/A50-xds-outlier-detection.md +++ b/A50-xds-outlier-detection.md @@ -284,7 +284,7 @@ Envoy defines some errors as "external" and some as "local origin", and their sp ### Excluding Locally-Initiated Client-Side Cancellations -Locally-initiated client-side cancellations (`hedging cancellations`, application `CANCELLED`, and `DEADLINE_EXCEEDED`) are excluded from outlier detection counting (`successCount` and `failureCount`). For locally-initiated cancellations (`hedging cancellations` of non-winning sibling attempts and application-initiated cancellations), this aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. For `DEADLINE_EXCEEDED`, this differs from Envoy (which counts deadline expirations as failures for outlier detection); however, because deadline expiration semantics vary between Envoy and gRPC, and implementation-wise it is much simpler to handle `DEADLINE_EXCEEDED` identically to cancellation, gRPC treats it as a client-side cancellation. +Locally-initiated client-side cancellations (`hedging cancellations`, application `CANCELLED`, and `DEADLINE_EXCEEDED`) are excluded from outlier detection counting (`successCount` and `failureCount`). For locally-initiated cancellations (`hedging cancellations` of non-winning sibling attempts and application-initiated cancellations), this aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. For `DEADLINE_EXCEEDED`, this differs from Envoy (which counts deadline expirations as failures for outlier detection); however, because deadline expiration semantics vary between Envoy and gRPC, and because a deadline expiration cannot be definitively attributed to a server failure rather than a network delay, gRPC treats it as a client-side cancellation. ### Map Entry Source From ae2658636c94357e4bf2fdfe0b0246ab5d0d0db5 Mon Sep 17 00:00:00 2001 From: AgraVator Date: Wed, 5 Aug 2026 15:36:43 +0530 Subject: [PATCH 5/8] A50 update: fix markdown formatting of hedging cancellations --- A50-xds-outlier-detection.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/A50-xds-outlier-detection.md b/A50-xds-outlier-detection.md index c74f9c632..4897eab13 100644 --- a/A50-xds-outlier-detection.md +++ b/A50-xds-outlier-detection.md @@ -137,7 +137,7 @@ When the `outlier_detection` LB policy receives an address update, it will creat When the child policy asks for a subchannel, the `outlier_detection` will wrap the subchannel with a wrapper (see [Subchannel Wrapper section](#subchannel-wrapper)). Then, the subchannel wrapper will be added to the list in the map entry for its address, if that map entry exists. If there is no map entry, or if the subchannel is created with multiple addresses, the subchannel will be ignored for outlier detection. If that address is currently ejected, that subchannel wrapper's `eject` method will be called. -The `outlier_detection` LB policy will provide a picker that delegates to the child policy's picker, and when the request finishes, increment the corresponding counter in the map entry referenced by the subchannel wrapper that was picked. Locally-initiated client-side cancellations (`hedging cancellations`, application `CANCELLED`, and `DEADLINE_EXCEEDED`) MUST be excluded from `successCount` and `failureCount`. If both the `success_rate_ejection` and `failure_percentage_ejection` fields are unset in the configuration, the picker should not do that counting. +The `outlier_detection` LB policy will provide a picker that delegates to the child policy's picker, and when the request finishes, increment the corresponding counter in the map entry referenced by the subchannel wrapper that was picked. Locally-initiated client-side cancellations (hedging cancellations, application `CANCELLED`, and `DEADLINE_EXCEEDED`) MUST be excluded from `successCount` and `failureCount`. If both the `success_rate_ejection` and `failure_percentage_ejection` fields are unset in the configuration, the picker should not do that counting. The `outlier_detection` LB policy will have a timer that triggers on a period determined by the `interval` config option, and does the following: @@ -170,7 +170,7 @@ To un-eject an address, set the current ejection timestamp to `null` and call `u ### Call Counter -This design is based directly on Envoy's implementation. The object contains two buckets, and each bucket has a number counting successes (`successCount`), and another counting failures (`failureCount`). The active bucket is updated each time a call finishes, excluding locally-initiated client-side cancellations (`hedging cancellations`, application `CANCELLED`, and `DEADLINE_EXCEEDED`). When the timer triggers, the inactive bucket is zeroed and swapped with the active bucket. Then the inactive bucket contains the number of successes and failures since the last time the timer triggered. Those numbers are used to evaluate the ejection criteria. +This design is based directly on Envoy's implementation. The object contains two buckets, and each bucket has a number counting successes (`successCount`), and another counting failures (`failureCount`). The active bucket is updated each time a call finishes, excluding locally-initiated client-side cancellations (hedging cancellations, application `CANCELLED`, and `DEADLINE_EXCEEDED`). When the timer triggers, the inactive bucket is zeroed and swapped with the active bucket. Then the inactive bucket contains the number of successes and failures since the last time the timer triggered. Those numbers are used to evaluate the ejection criteria. ### Subchannel Wrapper @@ -284,7 +284,7 @@ Envoy defines some errors as "external" and some as "local origin", and their sp ### Excluding Locally-Initiated Client-Side Cancellations -Locally-initiated client-side cancellations (`hedging cancellations`, application `CANCELLED`, and `DEADLINE_EXCEEDED`) are excluded from outlier detection counting (`successCount` and `failureCount`). For locally-initiated cancellations (`hedging cancellations` of non-winning sibling attempts and application-initiated cancellations), this aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. For `DEADLINE_EXCEEDED`, this differs from Envoy (which counts deadline expirations as failures for outlier detection); however, because deadline expiration semantics vary between Envoy and gRPC, and because a deadline expiration cannot be definitively attributed to a server failure rather than a network delay, gRPC treats it as a client-side cancellation. +Locally-initiated client-side cancellations (hedging cancellations, application `CANCELLED`, and `DEADLINE_EXCEEDED`) are excluded from outlier detection counting (`successCount` and `failureCount`). For locally-initiated cancellations (hedging cancellations of non-winning sibling attempts and application-initiated cancellations), this aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. For `DEADLINE_EXCEEDED`, this differs from Envoy (which counts deadline expirations as failures for outlier detection); however, because deadline expiration semantics vary between Envoy and gRPC, and because a deadline expiration cannot be definitively attributed to a server failure rather than a network delay, gRPC treats it as a client-side cancellation. ### Map Entry Source From e3735a25d496b3039dcd3b7d0a81b43a29903bc1 Mon Sep 17 00:00:00 2001 From: AgraVator Date: Wed, 19 Aug 2026 11:24:33 +0530 Subject: [PATCH 6/8] A50: address review feedback on client-side cancellation wording --- A50-xds-outlier-detection.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/A50-xds-outlier-detection.md b/A50-xds-outlier-detection.md index 4897eab13..9801728b1 100644 --- a/A50-xds-outlier-detection.md +++ b/A50-xds-outlier-detection.md @@ -137,7 +137,7 @@ When the `outlier_detection` LB policy receives an address update, it will creat When the child policy asks for a subchannel, the `outlier_detection` will wrap the subchannel with a wrapper (see [Subchannel Wrapper section](#subchannel-wrapper)). Then, the subchannel wrapper will be added to the list in the map entry for its address, if that map entry exists. If there is no map entry, or if the subchannel is created with multiple addresses, the subchannel will be ignored for outlier detection. If that address is currently ejected, that subchannel wrapper's `eject` method will be called. -The `outlier_detection` LB policy will provide a picker that delegates to the child policy's picker, and when the request finishes, increment the corresponding counter in the map entry referenced by the subchannel wrapper that was picked. Locally-initiated client-side cancellations (hedging cancellations, application `CANCELLED`, and `DEADLINE_EXCEEDED`) MUST be excluded from `successCount` and `failureCount`. If both the `success_rate_ejection` and `failure_percentage_ejection` fields are unset in the configuration, the picker should not do that counting. +The `outlier_detection` LB policy will provide a picker that delegates to the child policy's picker, and when the request finishes, updates the counter in the map entry referenced by the subchannel wrapper that was picked. If both the `success_rate_ejection` and `failure_percentage_ejection` fields are unset in the configuration, the picker should not do that counting. The `outlier_detection` LB policy will have a timer that triggers on a period determined by the `interval` config option, and does the following: @@ -170,7 +170,7 @@ To un-eject an address, set the current ejection timestamp to `null` and call `u ### Call Counter -This design is based directly on Envoy's implementation. The object contains two buckets, and each bucket has a number counting successes (`successCount`), and another counting failures (`failureCount`). The active bucket is updated each time a call finishes, excluding locally-initiated client-side cancellations (hedging cancellations, application `CANCELLED`, and `DEADLINE_EXCEEDED`). When the timer triggers, the inactive bucket is zeroed and swapped with the active bucket. Then the inactive bucket contains the number of successes and failures since the last time the timer triggered. Those numbers are used to evaluate the ejection criteria. +This design is based directly on Envoy's implementation. The object contains two buckets, and each bucket has a number counting successes, and another counting failures. The active bucket is updated each time a call finishes, excluding locally-initiated client-side cancellations (hedging cancellations, application cancellation, and deadline exceeded). When the timer triggers, the inactive bucket is zeroed and swapped with the active bucket. Then the inactive bucket contains the number of successes and failures since the last time the timer triggered. Those numbers are used to evaluate the ejection criteria. ### Subchannel Wrapper @@ -284,7 +284,7 @@ Envoy defines some errors as "external" and some as "local origin", and their sp ### Excluding Locally-Initiated Client-Side Cancellations -Locally-initiated client-side cancellations (hedging cancellations, application `CANCELLED`, and `DEADLINE_EXCEEDED`) are excluded from outlier detection counting (`successCount` and `failureCount`). For locally-initiated cancellations (hedging cancellations of non-winning sibling attempts and application-initiated cancellations), this aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. For `DEADLINE_EXCEEDED`, this differs from Envoy (which counts deadline expirations as failures for outlier detection); however, because deadline expiration semantics vary between Envoy and gRPC, and because a deadline expiration cannot be definitively attributed to a server failure rather than a network delay, gRPC treats it as a client-side cancellation. +Locally-initiated client-side cancellations (hedging cancellations, application cancellation, and deadline exceeded) are excluded from outlier detection counting. For locally-initiated cancellations (hedging cancellations of non-winning sibling attempts and application-initiated cancellations), this aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. For deadline exceeded, this differs from Envoy (which counts deadline expirations as failures for outlier detection). In gRPC, client-side deadline expiration cannot be reliably distinguished from other client cancellations cross-language, and a deadline expiration cannot be definitively attributed to a server failure rather than a network or client-side delay. Therefore, gRPC treats client-side deadline expiration as a locally-initiated cancellation and excludes it from outlier detection counting. ### Map Entry Source From 0b047bab179c1aa5f33b85037ad4763239d437c2 Mon Sep 17 00:00:00 2001 From: AgraVator Date: Wed, 19 Aug 2026 11:34:34 +0530 Subject: [PATCH 7/8] A50: clarify non-exhaustive client cancellations and rewrite rationale --- A50-xds-outlier-detection.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/A50-xds-outlier-detection.md b/A50-xds-outlier-detection.md index 9801728b1..8d2cebd52 100644 --- a/A50-xds-outlier-detection.md +++ b/A50-xds-outlier-detection.md @@ -170,7 +170,7 @@ To un-eject an address, set the current ejection timestamp to `null` and call `u ### Call Counter -This design is based directly on Envoy's implementation. The object contains two buckets, and each bucket has a number counting successes, and another counting failures. The active bucket is updated each time a call finishes, excluding locally-initiated client-side cancellations (hedging cancellations, application cancellation, and deadline exceeded). When the timer triggers, the inactive bucket is zeroed and swapped with the active bucket. Then the inactive bucket contains the number of successes and failures since the last time the timer triggered. Those numbers are used to evaluate the ejection criteria. +This design is based directly on Envoy's implementation. The object contains two buckets, and each bucket has a number counting successes, and another counting failures. The active bucket is updated each time a call finishes, excluding client-initiated cancellations (such as application cancellations, cancellations of non-winning hedged attempts, etc.) and client-side deadline expirations. When the timer triggers, the inactive bucket is zeroed and swapped with the active bucket. Then the inactive bucket contains the number of successes and failures since the last time the timer triggered. Those numbers are used to evaluate the ejection criteria. ### Subchannel Wrapper @@ -282,9 +282,13 @@ Envoy's specification of outlier detection includes the ejection criteria Consec Envoy defines some errors as "external" and some as "local origin", and their specification of outlier detection allows separate configurations for handling each of them. gRPC does not separate errors that way, so there is no way to split them like that and handle those two categories separately. -### Excluding Locally-Initiated Client-Side Cancellations +### Excluding Client-Initiated Cancellations and Deadline Expirations -Locally-initiated client-side cancellations (hedging cancellations, application cancellation, and deadline exceeded) are excluded from outlier detection counting. For locally-initiated cancellations (hedging cancellations of non-winning sibling attempts and application-initiated cancellations), this aligns with Envoy's `resetStream()` behavior and prevents false-positive ejections during hedging. For deadline exceeded, this differs from Envoy (which counts deadline expirations as failures for outlier detection). In gRPC, client-side deadline expiration cannot be reliably distinguished from other client cancellations cross-language, and a deadline expiration cannot be definitively attributed to a server failure rather than a network or client-side delay. Therefore, gRPC treats client-side deadline expiration as a locally-initiated cancellation and excludes it from outlier detection counting. +Client-initiated cancellations (such as application cancellations, cancellations of non-winning hedged attempts, etc.) and client-side deadline expirations are excluded from outlier detection counting. + +Excluding client cancellations aligns with Envoy's `resetStream()` behavior and prevents false-positive endpoint ejections when hedging is enabled. + +Excluding client-side deadline expirations differs from Envoy, which counts timeouts as failures for outlier detection. However, in gRPC, client-side deadline expirations cannot be reliably distinguished from other client-initiated cancellations cross-language, and a deadline expiration cannot be definitively attributed to an endpoint failure rather than client-side or network delays. Therefore, client-side deadline expirations are treated identically to client cancellations and excluded from outlier detection counting. ### Map Entry Source From c72a5858fcb706c77047349668f71530daa7abc6 Mon Sep 17 00:00:00 2001 From: AgraVator Date: Wed, 19 Aug 2026 11:36:33 +0530 Subject: [PATCH 8/8] A50: format Rationale subsection into single paragraph --- A50-xds-outlier-detection.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/A50-xds-outlier-detection.md b/A50-xds-outlier-detection.md index 8d2cebd52..41c91b75e 100644 --- a/A50-xds-outlier-detection.md +++ b/A50-xds-outlier-detection.md @@ -284,11 +284,7 @@ Envoy defines some errors as "external" and some as "local origin", and their sp ### Excluding Client-Initiated Cancellations and Deadline Expirations -Client-initiated cancellations (such as application cancellations, cancellations of non-winning hedged attempts, etc.) and client-side deadline expirations are excluded from outlier detection counting. - -Excluding client cancellations aligns with Envoy's `resetStream()` behavior and prevents false-positive endpoint ejections when hedging is enabled. - -Excluding client-side deadline expirations differs from Envoy, which counts timeouts as failures for outlier detection. However, in gRPC, client-side deadline expirations cannot be reliably distinguished from other client-initiated cancellations cross-language, and a deadline expiration cannot be definitively attributed to an endpoint failure rather than client-side or network delays. Therefore, client-side deadline expirations are treated identically to client cancellations and excluded from outlier detection counting. +Client-initiated cancellations (such as application cancellations, cancellations of non-winning hedged attempts, etc.) and client-side deadline expirations are excluded from outlier detection counting. Excluding client cancellations aligns with Envoy's `resetStream()` behavior and prevents false-positive endpoint ejections when hedging is enabled. Excluding client-side deadline expirations differs from Envoy, which counts timeouts as failures for outlier detection. However, in gRPC, client-side deadline expirations cannot be reliably distinguished from other client-initiated cancellations cross-language, and a deadline expiration cannot be definitively attributed to an endpoint failure rather than client-side or network delays. Therefore, client-side deadline expirations are treated identically to client cancellations and excluded from outlier detection counting. ### Map Entry Source