Safeguard
Security Guides•

Which Kestrel limits should an ASP.NET Core API set?

Set Kestrel MaxRequestBodySize per endpoint, RequestHeadersTimeout, KeepAliveTimeout and MaxConcurrentConnections explicitly instead of trusting defaults.

Safeguard Security Team
4 min read

An ASP.NET Core API on Kestrel should set MaxRequestBodySize (ideally per endpoint), RequestHeadersTimeout, KeepAliveTimeout and MaxConcurrentConnections explicitly in ConfigureKestrel. Microsoft documents these as options "especially useful in Internet facing deployments". Writing the values down means a version upgrade cannot silently change your exposure.

Where the settings live

Kestrel limits sit on KestrelServerOptions.Limits, configured in Program.cs through builder.WebHost.ConfigureKestrel. The relevant ones for a backend developer:

LimitWhat it controls
MaxRequestBodySizeMaximum size of any request body, in bytes
RequestHeadersTimeoutMaximum time the server spends receiving request headers
KeepAliveTimeoutHow long an idle keep alive connection stays open
MaxConcurrentConnectionsMaximum number of open connections
MinRequestBodyDataRateMinimum rate at which a client must send body data. See the slow client post

Defaults to check against your version

The ASP.NET Core 5.0 version of the Kestrel options page lists these defaults: a maximum request body of 30,000,000 bytes (about 28.6 MB), a request headers timeout of 30 seconds, a keep alive timeout of 2 minutes, and an unlimited number of connections (null). The current page for newer versions shows the options and examples but may state values differently, so read the page for the version you run, and prefer to set values yourself.

A 28.6 MB default body is generous for a JSON API. If a login endpoint accepts that much, you are paying memory and CPU for requests that should be rejected after a few kilobytes.

Per endpoint body limits

The documentation recommends the RequestSizeLimit attribute to override the limit in an MVC app, and shows the IHttpMaxRequestBodySizeFeature for middleware. The feature has an IsReadOnly property, and setting the limit after the app has started to read the request throws an exception.

builder.WebHost.ConfigureKestrel(o =>
{
    o.Limits.MaxRequestBodySize = 1_000_000;      // 1 MB default for the API
    o.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(15);
    o.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(1);
    o.Limits.MaxConcurrentConnections = 1000;
});
[RequestSizeLimit(50_000_000)]
[HttpPost("upload")]
public IActionResult Upload() { /* stream to storage */ }

Set a small default, then raise it only on the route that needs it.

Two things that change the picture

  1. Behind IIS in the out of process model, the documentation says IIS sets the limit and Kestrel's body size limit is disabled. Check which layer owns the limit in your hosting model.
  2. Timeouts and data rate limits are not enforced while a debugger is attached to the Kestrel process, as the docs state. Do not test limits with a debugger running.

Steps

  1. Pick a small global MaxRequestBodySize that fits your normal payloads.
  2. Raise it with RequestSizeLimit only for upload routes, and stream those bodies.
  3. Set RequestHeadersTimeout and KeepAliveTimeout explicitly.
  4. Choose MaxConcurrentConnections from your load tests and instance size.
  5. Confirm which layer enforces limits if you sit behind a proxy or IIS.
  6. Test with an oversized body, a slow header client and many idle connections, without a debugger.

Try it yourself

Click through it at your own pace, or open it full screen. See how a live scan exercises a running app from the outside.

Quick check

What happens when a body exceeds MaxRequestBodySize?

The request is rejected by Kestrel before your code reads the rest of it. Return a clear 413 from your own handlers where you apply limits yourself.

Is MaxConcurrentConnections the same as a rate limit?

No. It caps open connections. Rate limiting by client is a separate control. See which ASP.NET Core rate limiter to use.

Safeguard dependency scanning tracks the NuGet packages your API ships, with reachability analysis to separate reachable findings from noise, and the free scan is at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.