Skip to main content

Command Palette

Search for a command to run...

High Performance Networking in .NET with Kestrel and YARP

Updated
4 min read
High Performance Networking in .NET with Kestrel and YARP
P
Senior Software Engineer specialising in cloud architecture, distributed systems, and modern .NET development, with over two decades of experience designing and delivering enterprise platforms in financial, insurance, and high-scale commercial environments. My focus is on building systems that are reliable, scalable, and maintainable over the long term. I’ve led modernisation initiatives moving legacy platforms to cloud-native Azure architectures, designed high-throughput streaming solutions to eliminate performance bottlenecks, and implemented secure microservices environments using container-based deployment models and event-driven integration patterns. From an architecture perspective, I have strong practical experience applying approaches such as Vertical Slice Architecture, Domain-Driven Design, Clean Architecture, and Hexagonal Architecture. I’m particularly interested in modular system design that balances delivery speed with long-term sustainability, and I enjoy solving complex problems involving distributed workflows, performance optimisation, and system reliability. I enjoy mentoring engineers, contributing to architectural decisions, and helping teams simplify complex systems into clear, maintainable designs. I’m always open to connecting with other engineers, architects, and technology leaders working on modern cloud and distributed system challenges.

I've continuously sought effective solutions for building high performance applications. Among the various technologies I've worked with, Kestrel and YARP have emerged as powerful tools, particularly when optimising network performance and scalability in .NET applications. Below, I'll share deeper insights and advanced techniques that I've discovered and refined through experience, aiming to help you harness these powerful frameworks effectively.

A look at Kestrel's Performance

Kestrel's introduction was transformative for the ASP.NET community. Built specifically for high performance, Kestrel supports asynchronous request handling, dramatically improving scalability. My initial adoption of Kestrel required an understanding beyond basic configurations to achieve enterprise level performance.

I soon realised that tuning connection limits, keep alive settings, and request buffering had a direct impact on throughput. These optimisations significantly improved handling large spikes in web traffic without compromising service reliability.

An example of optimising Kestrel's configurations:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 200_000;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 20_000;
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(3);
    serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(60);
    serverOptions.Limits.Http2.MaxStreamsPerConnection = 100;
});

Leveraging YARP for Scalability

In large distributed applications, managing multiple microservices becomes complex. My experience deploying YARP showed me its exceptional capabilities for request routing, load balancing, and dynamic configuration.

A particularly valuable feature of YARP is its advanced session affinity, which allows sticky sessions to particular servers, enhancing performance for stateful services. Here's a look at configuring session affinity:

"Clusters": {
  "webCluster": {
    "SessionAffinity": {
      "Enabled": true,
      "Policy": "Cookie",
      "Cookie": {
        "Name": "AffinityCookie",
        "Expiration": "00:30:00"
      }
    },
    "Destinations": {
      "server1": {"Address": "https://localhost:7001"},
      "server2": {"Address": "https://localhost:7002"}
    }
  }
}

Implementing affinity was crucial in maintaining user state without extensive overhead in our user intensive applications.

Load Balancing Strategies

Load balancing in YARP can be customised extensively. I’ve found customising the load balancing strategy to fit specific application needs can lead to substantial performance gains.

An example of configuring a round robin load balancer with custom health checks:

"HealthCheck": {
  "Active": {
    "Enabled": true,
    "Interval": "00:00:10",
    "Timeout": "00:00:05",
    "Policy": "ConsecutiveFailures",
    "FailureThreshold": 3
  }
},
"LoadBalancing": {
  "Policy": "RoundRobin"
}

Through iterative testing, I discovered that tuning the health check interval and thresholds was pivotal in maintaining optimal load distribution and quick recovery from outages.

Diagnostic and Observability Techniques

Achieving high performance isn't only about initial setup but also about maintaining visibility. I've integrated structured logging and distributed tracing through OpenTelemetry, enabling detailed diagnostics and facilitating quicker issue resolution.

Here's an example of integrating OpenTelemetry with Kestrel:

builder.Services.AddOpenTelemetryTracing(builder =>
{
    builder
        .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MyKestrelApp"))
        .AddAspNetCoreInstrumentation()
        .AddHttpClientInstrumentation()
        .AddConsoleExporter();
});

This setup provided crucial insights during performance tuning, helping identify bottlenecks and latencies precisely.

Security and Performance Considerations

Security often impacts performance. Initially, configuring HTTPS introduced performance overhead, but fine tuning certificate handling and connection settings allowed me to mitigate these effects.

Optimising certificate loading and SSL configurations:

serverOptions.ListenAnyIP(5001, listenOptions =>
{
    listenOptions.UseHttps(httpsOptions =>
    {
        httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
            CertificateLoader.LoadFromStoreCert("MyCertificate", "MyStore", StoreLocation.CurrentUser, true);
    });
});

Through careful management of certificates and encryption settings, performance impact was reduced significantly without compromising security.

Other Performance Tweaks

Real deployment scenarios have continually taught me invaluable lessons. For instance, leveraging the reverse proxy cache of YARP dramatically reduced latency and server load:

"Caching": {
  "Enabled": true,
  "ExpirationTime": "00:05:00"
}

Caching also significantly reduced response times and improved client experience during peak traffic hours.

Benchmarking and Continuous Optimisation

Performance is not static; regular benchmarking has become integral to my process. Using BenchmarkDotNet for micro benchmarks and Apache JMeter for load testing, I've maintained and continually improved performance.

BenchmarkDotNet example for a basic HTTP endpoint:

[Benchmark]
public async Task TestEndpointPerformance()
{
    var response = await _httpClient.GetAsync("https://localhost:5001/api/data");
    response.EnsureSuccessStatusCode();
}

Regular testing and analysis informed ongoing optimisations and ensured consistent high performance.

My experience with Kestrel and YARP has revealed a wealth of potential when building high performance, scalable .NET applications. By mastering advanced configuration, observability, security, and continuous benchmarking, I've managed to build systems resilient to heavy loads and capable of maintaining exceptional performance.

The ideas outlined here come from practical experience, experimentation, and iterative learning. My advice is immerse yourself deeply in these tools, continually refine your approach, play around, and never underestimate the value of thorough testing and monitoring.