Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changesets/fix_caroline_revert_8765.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
### Return 503 for rate limit traffic shaping ([PR #9013](https://github.com/apollographql/router/pull/9013))

Reverts [PR #8765](https://github.com/apollographql/router/pull/8765).

When the router's rate limit or buffer capacity is exceeded, it now returns HTTP 503 (Service Unavailable) instead of HTTP 429 (Too Many Requests).

HTTP 429 implies that a specific client has sent too many requests and should back off. HTTP 503 more accurately reflects the situation: the router is temporarily unable to handle the request due to overall service load, not because of the behavior of any individual client.

This change affects both router-level and subgraph-level rate limiting. Documentation has been updated to reflect the new status code.

By [@carodewig](https://github.com/carodewig) in https://github.com/apollographql/router/pull/9013
10 changes: 5 additions & 5 deletions apollo-router/src/plugins/traffic_shaping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ impl PluginPrivate for TrafficShaping {
let response: Result<RouterResponse, BoxError> = future.await;
if matches!(response, Err(ref err) if err.is::<Overloaded>()) {
Ok(RouterResponse::error_builder()
.status_code(StatusCode::TOO_MANY_REQUESTS)
.status_code(StatusCode::SERVICE_UNAVAILABLE)
.error(rate_limit_error())
.context(ctx)
.build()
Expand Down Expand Up @@ -382,7 +382,7 @@ impl PluginPrivate for TrafficShaping {
Err(err) if err.is::<Overloaded>() => {
// TODO add metrics
Ok(SubgraphResponse::error_builder()
.status_code(StatusCode::TOO_MANY_REQUESTS)
.status_code(StatusCode::SERVICE_UNAVAILABLE)
.subgraph_name(subgraph_name)
.error(rate_limit_error())
.context(ctx)
Expand Down Expand Up @@ -1055,7 +1055,7 @@ mod test {
.await
.expect("it responded");

assert_eq!(StatusCode::TOO_MANY_REQUESTS, response.response.status());
assert_eq!(StatusCode::SERVICE_UNAVAILABLE, response.response.status());

tokio::time::sleep(Duration::from_millis(300)).await;

Expand Down Expand Up @@ -1186,7 +1186,7 @@ mod test {
.call(RouterRequest::fake_builder().build().unwrap())
.await
.unwrap();
assert_eq!(StatusCode::TOO_MANY_REQUESTS, response.response.status());
assert_eq!(StatusCode::SERVICE_UNAVAILABLE, response.response.status());
let j: serde_json::Value = serde_json::from_slice(
&router::body::into_bytes(response.response)
.await
Expand Down Expand Up @@ -1284,7 +1284,7 @@ mod test {
let mut results = tasks.join_all().await.into_iter();

let response = results.next().unwrap().unwrap().response;
assert_eq!(StatusCode::TOO_MANY_REQUESTS, response.status());
assert_eq!(StatusCode::SERVICE_UNAVAILABLE, response.status());

let response = results.next().unwrap().unwrap().response;
assert_eq!(StatusCode::GATEWAY_TIMEOUT, response.status());
Expand Down
4 changes: 2 additions & 2 deletions apollo-router/tests/integration/traffic_shaping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,12 @@ async fn test_router_rate_limit() -> Result<(), BoxError> {
assert_yaml_snapshot!(response);

let (_, response) = router.execute_default_query().await;
assert_eq!(response.status(), 429);
assert_eq!(response.status(), 503);
let response = response.text().await?;
assert!(response.contains("REQUEST_RATE_LIMITED"));
assert_yaml_snapshot!(response);

router.assert_metrics_contains(r#"http_server_request_duration_seconds_count{error_type="Too Many Requests",http_request_method="POST",http_response_status_code="429""#, None).await;
router.assert_metrics_contains(r#"http_server_request_duration_seconds_count{error_type="Service Unavailable",http_request_method="POST",http_response_status_code="503""#, None).await;

router.graceful_shutdown().await;
Ok(())
Expand Down
11 changes: 6 additions & 5 deletions docs/source/routing/errors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@

</Property>

<Property name="429" short="Too many requests">

Request traffic exceeded configured rate limits. See [client side traffic shaping](/router/configuration/traffic-shaping/#client-side-traffic-shaping).

</Property>
<Property name="499" short="Request canceled by client">

The request was canceled because the client closed the connection, possibly due to a client side timeout.
Expand All @@ -58,6 +53,12 @@

</Property>

<Property name="503" short="Service unavailable">

Check notice on line 56 in docs/source/routing/errors.mdx

View check run for this annotation

Apollo Librarian / AI Style Review

docs/source/routing/errors.mdx#L56

**Word and Symbol Usage**: Numbers used in a code or CLI context should use numerals with code font. ```suggestion <Property name="`503`" short="Service unavailable"> ```

Request traffic exceeded your configured rate limits. See [client side traffic shaping](/router/configuration/traffic-shaping/#client-side-traffic-shaping).

Check notice on line 58 in docs/source/routing/errors.mdx

View check run for this annotation

Apollo Librarian / AI Style Review

docs/source/routing/errors.mdx#L58

**Language**: Use a hyphen for the compound adjective 'client-side'. **Text Formatting**: Avoid using vague phrases like 'See' followed by a link; use a rich noun or verb phrase and place links at the end of the sentence. **Voice**: The original text is slightly passive. Using 'Use' provides a more authoritative and helpful recommendation for the user. **Word and Symbol Usage**: Use a hyphen for "client-side" when it is used as a compound modifier before a noun. ```suggestion Request traffic exceeded your configured rate limits. See [client-side traffic shaping](/router/configuration/traffic-shaping/#client-side-traffic-shaping). ```

</Property>

<Property name="504" short="Request timed out">

The request was not able to complete within a configured amount of time. See [client side traffic shaping timeouts](/router/configuration/traffic-shaping/#timeouts).
Expand Down
2 changes: 2 additions & 0 deletions docs/source/routing/performance/traffic-shaping.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@

This rate limiting applies to all requests, there is no filtering per IP or other criteria.

If the router-level rate limit is hit, Apollo Router returns a [HTTP 503 status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/503) to indicate that the service is unavailable.

Check warning on line 58 in docs/source/routing/performance/traffic-shaping.mdx

View check run for this annotation

Apollo Librarian / AI Style Review

docs/source/routing/performance/traffic-shaping.mdx#L58

**Products and Features**: Do not use articles like "the" before standalone product names like Apollo Router. **Text Formatting**: Use code font for symbols like HTTP status codes. Avoid vague link text; use a descriptive noun phrase and move the link to the end of the sentence. **Word and Symbol Usage**: Numbers used in a code or technical context should be numerals with code font. ```suggestion If the router-level rate limit is hit, Apollo Router returns a [HTTP 503 status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/503) to indicate that the service is unavailable. ```

### Timeouts

The router applies a default timeout of 30 seconds for all requests, including the following:
Expand Down
Loading