Kestrel Configuration in ASP.NET Core

Kestrel is the cross-platform web server that ships with ASP.NET Core. It is the default server, running in-process with your application, and it is fast — consistently ranking among the top performers in the TechEmpower benchmarks. Understanding how to configure it properly is essential for production deployments.

Default Behaviour

When you call WebApplication.CreateBuilder(args), Kestrel is configured as the default server. Without any explicit configuration, it listens on http://localhost:5000 and https://localhost:5001 in Development (via launchSettings.json).

Configuring Endpoints in Code

For explicit control over which addresses Kestrel listens on:

Example.cs
var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(options =>
{
    // Listen on port 8080 for HTTP
    options.ListenAnyIP(8080);

    // Listen on port 8443 for HTTPS with a certificate
    options.ListenAnyIP(8443, listenOptions =>
    {
        listenOptions.UseHttps("certificate.pfx", "password");
    });

    // Listen on a Unix socket (useful for reverse proxy setups)
    options.ListenUnixSocket("/tmp/kestrel.sock");
});

var app = builder.Build();
app.Run();

ListenAnyIP binds to all network interfaces. Use ListenLocalhost to restrict to loopback, or Listen with a specific IPAddress for targeted binding.

Configuring via appsettings.json

For deployments where you do not want to recompile to change endpoints, use configuration:

appsettings.json
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://*:8080"
      },
      "Https": {
        "Url": "https://*:8443",
        "Certificate": {
          "Path": "/etc/ssl/certs/app.pfx",
          "Password": "cert-password"
        }
      }
    }
  }
}

Kestrel reads this configuration automatically. You can also load certificates from the certificate store on Windows:

appsettings.json
{
  "Kestrel": {
    "Endpoints": {
      "Https": {
        "Url": "https://*:443",
        "Certificate": {
          "Subject": "*.example.com",
          "Store": "My",
          "Location": "CurrentUser"
        }
      }
    }
  }
}

Request and Connection Limits

Kestrel exposes several limits to protect your server from abuse:

Example.cs
builder.WebHost.ConfigureKestrel(options =>
{
    var limits = options.Limits;

    // Maximum request body size (default 30 MB)
    limits.MaxRequestBodySize = 50 * 1024 * 1024; // 50 MB

    // Maximum concurrent connections (default unlimited)
    limits.MaxConcurrentConnections = 1000;

    // Maximum concurrent upgraded connections (WebSockets)
    limits.MaxConcurrentUpgradedConnections = 500;

    // Request header timeout
    limits.RequestHeadersTimeout = TimeSpan.FromSeconds(30);

    // Keep-alive timeout
    limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);

    // Maximum request header size (default 32 KB)
    limits.MaxRequestHeadersTotalSize = 64 * 1024;

    // Maximum request header count
    limits.MaxRequestHeaderCount = 50;
});

These limits are your first line of defence against slowloris attacks, oversized uploads, and connection exhaustion.

Per-Endpoint Limits

You can also set limits on individual endpoints:

Example.cs
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(8080, listenOptions =>
    {
        listenOptions.UseHttps();
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
    });

    // File upload endpoint with larger body limit
    options.ListenAnyIP(8081, listenOptions =>
    {
        listenOptions.UseHttps();
    });
});

Or override the body size limit per endpoint at the application level:

Example.cs
app.MapPost("/upload", HandleUpload)
    .DisableAntiforgery()
    .WithMetadata(new RequestSizeLimitAttribute(200 * 1024 * 1024));

// Alternatively, for controllers:
[RequestSizeLimit(200 * 1024 * 1024)]
[HttpPost("upload")]
public IActionResult Upload(IFormFile file) { /* ... */ }

HTTP/2 and HTTP/3

Kestrel supports HTTP/2 by default over HTTPS. HTTP/3 (QUIC) can be enabled for improved performance on unreliable networks:

Example.cs
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(8443, listenOptions =>
    {
        listenOptions.UseHttps();
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
    });
});

HTTP/3 requires the Microsoft.AspNetCore.Server.Kestrel.Transport.Quic package and platform support (Windows 11+, Linux with libmsquic).

Running Behind a Reverse Proxy

In production, Kestrel typically runs behind a reverse proxy (Nginx, Caddy, YARP, or a cloud load balancer). Configure forwarded headers so your application sees the correct client IP and scheme:

Example.cs
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders =
        ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.1"));
});

var app = builder.Build();

app.UseForwardedHeaders();

Without this, HttpContext.Connection.RemoteIpAddress returns the proxy's address instead of the client's, and URL generation uses http instead of https.

Performance Tuning

For high-throughput scenarios, tune the transport layer:

Example.cs
builder.WebHost.ConfigureKestrel(options =>
{
    // Use the Socket transport (default)
    options.Limits.MinRequestBodyDataRate = new MinDataRate(
        bytesPerSecond: 100,
        gracePeriod: TimeSpan.FromSeconds(10));

    options.Limits.MinResponseDataRate = new MinDataRate(
        bytesPerSecond: 100,
        gracePeriod: TimeSpan.FromSeconds(10));
});

Minimum data rates protect against slow-read and slow-write attacks. If a client reads or writes slower than the threshold after the grace period, the connection is closed.

Key Takeaways

Kestrel is production-ready out of the box, but configuring it properly matters. Set appropriate request limits, enable HTTPS with proper certificates, and configure forwarded headers when running behind a reverse proxy. Use configuration files for endpoint setup so you can adjust bindings without redeploying code, and consider HTTP/2 and HTTP/3 for improved client performance.