Configure options for the ASP.NET Core Kestrel web server

The Kestrel web server has constraint configuration options that are especially useful in Internet-facing deployments. To configure Kestrel configuration options, call ConfigureKestrel in Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    // ...
});

Set constraints on the KestrelServerOptions.Limits property. This property holds an instance of the KestrelServerLimits class.

General limits

Keep-alive timeout

KeepAliveTimeout gets or sets the keep-alive timeout:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
});

This timeout is not enforced when a debugger is attached to the Kestrel process.

Maximum client connections

MaxConcurrentConnections gets or sets the maximum number of open connections:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
});

MaxConcurrentUpgradedConnections gets or sets the maximum number of open, upgraded connections:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
});

An upgraded connection is one that has been switched from HTTP to another protocol, such as WebSockets. After a connection is upgraded, it isn't counted against the MaxConcurrentConnections limit.

Maximum request body size

MaxRequestBodySize gets or sets the maximum allowed size of any request body in bytes.

The recommended approach to override the limit in an ASP.NET Core MVC app is to use the RequestSizeLimitAttribute attribute on an action method:

[RequestSizeLimit(100_000_000)]
public IActionResult Get()

The following example configures MaxRequestBodySize for all requests:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxRequestBodySize = 100_000_000;
});

The following example configures MaxRequestBodySize for a specific request using IHttpMaxRequestBodySizeFeature in a custom middleware:

app.Use(async (context, next) =>
{
    var httpMaxRequestBodySizeFeature = context.Features.Get<IHttpMaxRequestBodySizeFeature>();

    if (httpMaxRequestBodySizeFeature is not null)
        httpMaxRequestBodySizeFeature.MaxRequestBodySize = 10 * 1024;

    // ...

    await next(context);
});

If the app attempts to configure the limit on a request after it starts to read the request, an exception is thrown. Ue the IHttpMaxRequestBodySizeFeature.IsReadOnly property to check if it's safe to set the MaxRequestBodySize property.

When an app runs out-of-process behind the ASP.NET Core Module, IIS sets the limit and Kestrel's request body size limit is disabled.

Minimum request body data rate

Kestrel checks every second if data is arriving at the specified rate in bytes/second. If the rate drops below the minimum, the connection is timed out. The grace period is the amount of time Kestrel allows the client to increase its send rate up to the minimum. The rate isn't checked during that time. The grace period helps avoid dropping connections that are initially sending data at a slow rate because of TCP slow-start. A minimum rate also applies to the response.

MinRequestBodyDataRate gets or sets the request body minimum data rate in bytes/second. MinResponseDataRate gets or sets the response minimum data rate in bytes/second.

The following example configures MinRequestBodyDataRate and MinResponseDataRate for all requests:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MinRequestBodyDataRate = new MinDataRate(
        bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate = new MinDataRate(
        bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
});

The following example configures MinRequestBodyDataRate and MinResponseDataRate for a specific request using IHttpMinRequestBodyDataRateFeature and IHttpMinResponseDataRateFeature in a custom middleware:

app.Use(async (context, next) =>
{
    var httpMinRequestBodyDataRateFeature = context.Features
        .Get<IHttpMinRequestBodyDataRateFeature>();

    if (httpMinRequestBodyDataRateFeature is not null)
    {
        httpMinRequestBodyDataRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    var httpMinResponseDataRateFeature = context.Features
        .Get<IHttpMinResponseDataRateFeature>();

    if (httpMinResponseDataRateFeature is not null)
    {
        httpMinResponseDataRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    // ...

    await next(context);
});

IHttpMinResponseDataRateFeature isn't present in HttpContext.Features for HTTP/2 requests. Modifying rate limits on a per-request basis isn't generally supported for HTTP/2 because of the protocol's support for request multiplexing. However, IHttpMinRequestBodyDataRateFeature is still present in HttpContext.Features for HTTP/2 requests, because the read rate limit can still be disabled entirely on a per-request basis by setting IHttpMinResponseDataRateFeature.MinDataRate to null, even for an HTTP/2 request. Attempts to read IHttpMinRequestBodyDataRateFeature.MinDataRate or attempts to set it to a value other than null result in a NotSupportedException for HTTP/2 requests.

Server-wide rate limits configured via KestrelServerOptions.Limits still apply to both HTTP/1.x and HTTP/2 connections.

Request headers timeout

RequestHeadersTimeout gets or sets the maximum amount of time the server spends receiving request headers:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});

This timeout is not enforced when a debugger is attached to the Kestrel process.

HTTP/2 limits

The limits in this section are set on KestrelServerLimits.Http2.

Maximum streams per connection

MaxStreamsPerConnection limits the number of concurrent request streams per HTTP/2 connection. Excess streams are refused:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.MaxStreamsPerConnection = 100;
});

Header table size

HeaderTableSize limits the size of the header compression tables, in octets, the HPACK encoder and decoder on the server can use. The HPACK decoder decompresses HTTP headers for HTTP/2 connections:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.HeaderTableSize = 4096;
});

Maximum frame size

MaxFrameSize indicates the size of the largest frame payload that is allowed to be received, in octets:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.MaxFrameSize = 16_384;
});

Maximum request header size

MaxRequestHeaderFieldSize indicates the size of the maximum allowed size of a request header field sequence. This limit applies to both name and value sequences in their compressed and uncompressed representations:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.MaxRequestHeaderFieldSize = 8192;
});

Initial connection window size

InitialConnectionWindowSize indicates how much request body data the server is willing to receive and buffer at a time aggregated across all requests (streams) per connection:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.InitialConnectionWindowSize = 131_072;
});

Requests are also limited by InitialStreamWindowSize.

Initial stream window size

InitialStreamWindowSize indicates how much request body data the server is willing to receive and buffer at a time per stream:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.InitialStreamWindowSize = 98_304;
});

Requests are also limited by InitialConnectionWindowSize.

HTTP/2 keep alive ping configuration

Kestrel can be configured to send HTTP/2 pings to connected clients. HTTP/2 pings serve multiple purposes:

  • Keep idle connections alive. Some clients and proxy servers close connections that are idle. HTTP/2 pings are considered as activity on a connection and prevent the connection from being closed as idle.
  • Close unhealthy connections. Connections where the client doesn't respond to the keep alive ping in the configured time are closed by the server.

There are two configuration options related to HTTP/2 keep alive pings:

  • KeepAlivePingDelay is a TimeSpan that configures the ping interval. The server sends a keep alive ping to the client if it doesn't receive any frames for this period of time. Keep alive pings are disabled when this option is set to TimeSpan.MaxValue.
  • KeepAlivePingTimeout is a TimeSpan that configures the ping timeout. If the server doesn't receive any frames, such as a response ping, during this timeout then the connection is closed. Keep alive timeout is disabled when this option is set to TimeSpan.MaxValue.

The following example sets KeepAlivePingDelay and KeepAlivePingTimeout:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.KeepAlivePingDelay = TimeSpan.FromSeconds(30);
    serverOptions.Limits.Http2.KeepAlivePingTimeout = TimeSpan.FromMinutes(1);
});

Other options

Synchronous I/O

AllowSynchronousIO controls whether synchronous I/O is allowed for the request and response.

Warning

A large number of blocking synchronous I/O operations can lead to thread pool starvation, which makes the app unresponsive. Only enable AllowSynchronousIO when using a library that doesn't support asynchronous I/O.

The following example enables synchronous I/O:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.AllowSynchronousIO = true;
});

For information about other Kestrel options and limits, see:

Behavior with debugger attached

Certain timeouts and rate limits aren't enforced when a debugger is attached to a Kestrel process. For more information, see Behavior with debugger attached.

The Kestrel web server has constraint configuration options that are especially useful in Internet-facing deployments.

To provide more configuration after calling ConfigureWebHostDefaults, use ConfigureKestrel:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseStartup<Startup>();
        });

Set constraints on the Limits property of the KestrelServerOptions class. The Limits property holds an instance of the KestrelServerLimits class.

The following examples use the Microsoft.AspNetCore.Server.Kestrel.Core namespace:

using Microsoft.AspNetCore.Server.Kestrel.Core;

Note

KestrelServerOptions and endpoint configuration are configurable from configuration providers. Remaining Kestrel configuration must be configured in C# code.

General limits

Keep-alive timeout

KeepAliveTimeout

Gets or sets the keep-alive timeout. Defaults to 2 minutes.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

Maximum client connections

MaxConcurrentConnections
MaxConcurrentUpgradedConnections

The maximum number of concurrent open TCP connections can be set for the entire app with the following code:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

There's a separate limit for connections that have been upgraded from HTTP or HTTPS to another protocol (for example, on a WebSockets request). After a connection is upgraded, it isn't counted against the MaxConcurrentConnections limit.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

The maximum number of connections is unlimited (null) by default.

Maximum request body size

MaxRequestBodySize

The default maximum request body size is 30,000,000 bytes, which is approximately 28.6 MB.

The recommended approach to override the limit in an ASP.NET Core MVC app is to use the RequestSizeLimitAttribute attribute on an action method:

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

The following example shows how to configure the constraint for the app on every request:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

Override the setting on a specific request in middleware:

app.Run(async (context) =>
{
    context.Features.Get<IHttpMaxRequestBodySizeFeature>()
        .MaxRequestBodySize = 10 * 1024;

    var minRequestRateFeature =
        context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
    var minResponseRateFeature =
        context.Features.Get<IHttpMinResponseDataRateFeature>();

    if (minRequestRateFeature != null)
    {
        minRequestRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    if (minResponseRateFeature != null)
    {
        minResponseRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

An exception is thrown if the app configures the limit on a request after the app has started to read the request. There's an IsReadOnly property that indicates if the MaxRequestBodySize property is in read-only state, meaning it's too late to configure the limit.

When an app runs out-of-process behind the ASP.NET Core Module, Kestrel's request body size limit is disabled. IIS already sets the limit.

Minimum request body data rate

MinRequestBodyDataRate
MinResponseDataRate

Kestrel checks every second if data is arriving at the specified rate in bytes/second. If the rate drops below the minimum, the connection is timed out. The grace period is the amount of time Kestrel allows the client to increase its send rate up to the minimum. The rate isn't checked during that time. The grace period helps avoid dropping connections that are initially sending data at a slow rate because of TCP slow-start.

The default minimum rate is 240 bytes/second with a 5-second grace period.

A minimum rate also applies to the response. The code to set the request limit and the response limit is the same except for having RequestBody or Response in the property and interface names.

Here's an example that shows how to configure the minimum data rates in Program.cs:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

Override the minimum rate limits per request in middleware:

app.Run(async (context) =>
{
    context.Features.Get<IHttpMaxRequestBodySizeFeature>()
        .MaxRequestBodySize = 10 * 1024;

    var minRequestRateFeature =
        context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
    var minResponseRateFeature =
        context.Features.Get<IHttpMinResponseDataRateFeature>();

    if (minRequestRateFeature != null)
    {
        minRequestRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    if (minResponseRateFeature != null)
    {
        minResponseRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

The IHttpMinResponseDataRateFeature referenced in the prior sample isn't present in HttpContext.Features for HTTP/2 requests. Modifying rate limits on a per-request basis isn't generally supported for HTTP/2 because of the protocol's support for request multiplexing. However, the IHttpMinRequestBodyDataRateFeature is still present HttpContext.Features for HTTP/2 requests, because the read rate limit can still be disabled entirely on a per-request basis by setting IHttpMinResponseDataRateFeature.MinDataRate to null even for an HTTP/2 request. Attempting to read IHttpMinRequestBodyDataRateFeature.MinDataRate or attempting to set it to a value other than null will result in a NotSupportedException being thrown given an HTTP/2 request.

Server-wide rate limits configured via KestrelServerOptions.Limits still apply to both HTTP/1.x and HTTP/2 connections.

Request headers timeout

RequestHeadersTimeout

Gets or sets the maximum amount of time the server spends receiving request headers. Defaults to 30 seconds.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

HTTP/2 limits

The limits in this section are set on KestrelServerLimits.Http2.

Maximum streams per connection

MaxStreamsPerConnection

Limits the number of concurrent request streams per HTTP/2 connection. Excess streams are refused.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.MaxStreamsPerConnection = 100;
});

The default value is 100.

Header table size

HeaderTableSize

The HPACK decoder decompresses HTTP headers for HTTP/2 connections. HeaderTableSize limits the size of the header compression table that the HPACK decoder uses. The value is provided in octets and must be greater than zero (0).

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.HeaderTableSize = 4096;
});

The default value is 4096.

Maximum frame size

MaxFrameSize

Indicates the maximum allowed size of an HTTP/2 connection frame payload received or sent by the server. The value is provided in octets and must be between 2^14 (16,384) and 2^24-1 (16,777,215).

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.MaxFrameSize = 16384;
});

The default value is 2^14 (16,384).

Maximum request header size

MaxRequestHeaderFieldSize

Indicates the maximum allowed size in octets of request header values. This limit applies to both name and value in their compressed and uncompressed representations. The value must be greater than zero (0).

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.MaxRequestHeaderFieldSize = 8192;
});

The default value is 8,192.

Initial connection window size

InitialConnectionWindowSize

Indicates the maximum request body data in bytes the server buffers at one time, aggregated across all requests (streams) per connection. Requests are also limited by Http2.InitialStreamWindowSize. The value must be greater than or equal to 65,535 and less than 2^31 (2,147,483,648).

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.InitialConnectionWindowSize = 131072;
});

The default value is 128 KB (131,072).

Initial stream window size

InitialStreamWindowSize

Indicates the maximum request body data in bytes the server buffers at one time per request (stream). Requests are also limited by InitialConnectionWindowSize. The value must be greater than or equal to 65,535 and less than 2^31 (2,147,483,648).

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.InitialStreamWindowSize = 98304;
});

The default value is 96 KB (98,304).

HTTP/2 keep alive ping configuration

Kestrel can be configured to send HTTP/2 pings to connected clients. HTTP/2 pings serve multiple purposes:

  • Keep idle connections alive. Some clients and proxy servers close connections that are idle. HTTP/2 pings are considered as activity on a connection and prevent the connection from being closed as idle.
  • Close unhealthy connections. Connections where the client doesn't respond to the keep alive ping in the configured time are closed by the server.

There are two configuration options related to HTTP/2 keep alive pings:

  • KeepAlivePingDelay is a TimeSpan that configures the ping interval. The server sends a keep alive ping to the client if it doesn't receive any frames for this period of time. Keep alive pings are disabled when this option is set to TimeSpan.MaxValue. The default value is TimeSpan.MaxValue.
  • KeepAlivePingTimeout is a TimeSpan that configures the ping timeout. If the server doesn't receive any frames, such as a response ping, during this timeout then the connection is closed. Keep alive timeout is disabled when this option is set to TimeSpan.MaxValue. The default value is 20 seconds.
webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.KeepAlivePingDelay = TimeSpan.FromSeconds(30);
    serverOptions.Limits.Http2.KeepAlivePingTimeout = TimeSpan.FromSeconds(60);
});

Other options

Synchronous I/O

AllowSynchronousIO controls whether synchronous I/O is allowed for the request and response. The default value is false.

Warning

A large number of blocking synchronous I/O operations can lead to thread pool starvation, which makes the app unresponsive. Only enable AllowSynchronousIO when using a library that doesn't support asynchronous I/O.

The following example enables synchronous I/O:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.AllowSynchronousIO = true;
})

For information about other Kestrel options and limits, see: