Other 5xx codes
All HTTP status codes in ASP.NET Core
5xx Server error
The server cannot handle the request right now, because of overload or maintenance. A Retry-After header may say when to retry.
In ASP.NET Core: ASP.NET Core's rate limiter sends it by default when it rejects a request.
The StatusCodes constant, HttpStatusCode enum name, reason phrase, class, and how EnsureSuccessStatusCode() and the standard resilience handler treat 503.
| Constant | StatusCodes.Status503ServiceUnavailable |
|---|---|
| HttpStatusCode | HttpStatusCode.ServiceUnavailable |
| Reason phrase | Kestrel sends Service Unavailable |
| Class | 5xx, server error |
| IsSuccessStatusCode | false |
| EnsureSuccessStatusCode() | throws HttpRequestException: Response status code does not indicate success: 503 (Service Unavailable). |
| Standard resilience handler | retries it (treated as transient) |
Results.StatusCode(StatusCodes.Status503ServiceUnavailable)
Results.Problem(statusCode: StatusCodes.Status503ServiceUnavailable, detail: "...")StatusCode(StatusCodes.Status503ServiceUnavailable)
Problem(statusCode: StatusCodes.Status503ServiceUnavailable, detail: "...")What Results.Problem(statusCode: 503) sends (with AddProblemDetails()), as application/problem+json:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.6.4",
"title": "Service Unavailable",
"status": 503,
"traceId": "0HNA1B2C3D4E5:00000001"
}A controller's Problem(statusCode: 503) sends the same body.
A bare StatusCode(503) in an [ApiController] also gets a ProblemDetails body automatically; Results.StatusCode(503) in a minimal API sends an empty body unless you add UseStatusCodePages().
Setup
builder.Services.AddRateLimiter(o =>
o.AddFixedWindowLimiter("one", w => { w.PermitLimit = 1; w.Window = TimeSpan.FromMinutes(1); }));
app.UseRateLimiter();Request
GET /limited HTTP/1.1 (second request in the window)Response (recorded)
HTTP/1.1 503 Service UnavailableRateLimiterOptions.RejectionStatusCode defaults to 503, not 429. Clients and HttpClient's resilience handler treat 503 as a server problem.
Fix: Set o.RejectionStatusCode = StatusCodes.Status429TooManyRequests, and add Retry-After in OnRejected.
Setup
builder.Services.AddRateLimiter(o =>
{
o.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
o.AddFixedWindowLimiter("one", w => { w.PermitLimit = 1; w.Window = TimeSpan.FromMinutes(1); });
});
app.UseRateLimiter();
app.MapGet("/limited", () => "ok").RequireRateLimiting("one");Request
GET /limited HTTP/1.1 (second request in the window)Response (recorded)
HTTP/1.1 429 Too Many RequestsWith RejectionStatusCode set, rejected requests get 429. No Retry-After header is added unless you write one in OnRejected.
Every response on this page was recorded from ASP.NET Core 10.0.12 on Kestrel in the Production environment; the HttpClient rows come from .NET 10.0.12 and Microsoft.Extensions.Http.Resilience 10.10.0.
All HTTP status codes in ASP.NET Core