Building a Dynamic API Gateway with .NET 8 and YARP for Secure Microservice Routing

Mahmut Sarıkaya 5 dk okuma 7 Görüntülenme 0
Building a Dynamic API Gateway with .NET 8 and YARP for Secure Microservice Routing

Why a Dynamic API Gateway Matters

Ever wondered why some microservice architectures can add a new service overnight without touching the client code? The secret is a flexible API gateway that can discover, route, and protect traffic on the fly. In 2023, 68% of enterprises reported that static routing caused deployment bottlenecks, prompting a shift toward dynamic solutions. A gateway built on .NET 8 and YARP (Yet Another Reverse Proxy) gives you the performance of native code plus the agility of runtime configuration.

Getting Started: Prerequisites and Project Setup

Before writing a single line of routing logic, ensure your development machine runs .NET 8 SDK (released November 2023) and has access to a Git repository for version control. Create a clean web project that will host the gateway:

dotnet new web -n GatewayApp

Navigate into the folder and initialise Git – this helps you track configuration changes that affect routing decisions.

Integrating YARP in .NET 8

YARP is a Microsoft‑maintained library that abstracts reverse‑proxy concerns while exposing a low‑level pipeline for custom logic. Add the package with the exact version that matches the .NET runtime to avoid binding conflicts.

dotnet add package Microsoft.ReverseProxy --version 8.0.0

After the package is installed, open Program.cs and register the reverse‑proxy services.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddReverseProxy();
var app = builder.Build();
app.MapReverseProxy();
app.Run();

This minimal setup already forwards requests defined in a configuration file, but it lacks the dynamism we need.

Configuring Dynamic Routing

YARP can read routes and clusters from appsettings.json, but you can also implement IProxyConfigProvider to fetch data from a database or a service registry such as Consul. Below is a sample static configuration that you will later replace with a dynamic provider.

{
  "ReverseProxy": {
    "Routes": [
      {
        "RouteId": "orders",
        "ClusterId": "ordersCluster",
        "Match": { "Path": "/orders/{**catchAll}" }
      }
    ],
    "Clusters": [
      {
        "ClusterId": "ordersCluster",
        "Destinations": {
          "dest1": { "Address": "http://localhost:5001/" }
        }
      }
    ]
  }
}

To make routing truly dynamic, create a class that implements IProxyConfigProvider. The provider pulls the latest routes from a SQL table every 30 seconds and notifies YARP via ChangeToken. This pattern eliminates the need to restart the gateway when a new microservice is deployed.

public class SqlConfigProvider : IProxyConfigProvider {
    private volatile ProxyConfig _current;
    private readonly Timer _timer;
    public SqlConfigProvider(IDbConnection db) {
        LoadConfig(db);
        _timer = new Timer(_ => LoadConfig(db), null, TimeSpan.Zero, TimeSpan.FromSeconds(30));
    }
    private void LoadConfig(IDbConnection db) {
        // Query Routes and Clusters tables, build ProxyConfig instance
        var newConfig = new ProxyConfig(...);
        Interlocked.Exchange(ref _current, newConfig);
        _changeToken?.OnChange(() => {});
    }
    private CancellationChangeToken _changeToken = new CancellationChangeToken(new CancellationTokenSource().Token);
    public IProxyConfig GetConfig() => _current;
}

builder.Services.AddSingleton();
builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));

The example skips detailed SQL mapping for brevity, but the key idea is that the provider runs in the background and pushes updates without disrupting active connections.

Securing the Gateway with Authentication

An API gateway is the natural choke point for enforcing security policies. Using JWT bearer tokens is the most common approach in modern .NET microservices. Register the authentication scheme before the proxy middleware so every incoming request is validated.

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options => {
        options.Authority = "https://auth.example.com";
        options.Audience = "gateway";
        options.RequireHttpsMetadata = true;
        options.TokenValidationParameters = new TokenValidationParameters {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.FromMinutes(2)
        };
    });
app.UseAuthentication();
app.UseAuthorization();
app.MapReverseProxy();

With this setup, any request that fails token validation receives a 401 response before YARP even attempts to forward it. You can also add role‑based policies to restrict specific routes, for example allowing only users with the Admin role to reach the /admin microservice.

Implementing Runtime Route Updates

Beyond the SQL‑based provider, YARP supports a built‑in InMemoryConfigProvider that can be manipulated through a minimal API endpoint. Expose a POST /gateway/routes endpoint that accepts a JSON payload describing a new route and writes it into the in‑memory store. This technique is handy for CI/CD pipelines that push route definitions after a successful deployment.

app.MapPost("/gateway/routes", async (IProxyConfigProvider provider, RouteDefinition def) => {
    if (provider is InMemoryConfigProvider inMem) {
        inMem.Update(route => route.Add(def));
        return Results.Ok();
    }
    return Results.StatusCode(500);
});

Because the provider uses ChangeToken, YARP instantly picks up the new route without a restart, achieving true zero‑downtime deployments.

Performance Tips and Monitoring

YARP runs on top of ASP.NET Core’s Kestrel server, which can handle more than 100,000 requests per second on a modest VM when HTTP/2 is enabled. To keep latency under 5 ms, enable response caching for idempotent GET calls and configure HttpClientFactory with a pooled handler. Adding app.UseHttpMetrics() from the Prometheus.Net package gives you real‑time metrics for request count, latency percentiles, and error rates.

Don’t forget to tune the .NET garbage collector for server workloads: set DOTNET_GCServer=1 and consider DOTNET_GCHeapHardLimit to cap memory usage in containerised environments.

Conclusion

By combining .NET 8’s performance improvements with YARP’s extensible pipeline, you can build an API gateway that routes traffic dynamically, authenticates every call, and scales to enterprise‑level loads. The key takeaways are to externalise route definitions, use a custom IProxyConfigProvider for live updates, and place authentication middleware before the proxy. With these patterns, adding a new microservice becomes a matter of inserting a row in a database or sending a JSON payload to a management endpoint—no code redeployment required.

Author: Mahmut Sarıkaya — sarikayadev.com

Sources

Microsoft Docs – YARP documentation

Microsoft Docs – ASP.NET Core authentication

Official .NET 8 release notes (Nov 2023)

Etiketler: #.NET 8 #YARP #API gateway #dynamic routing #authentication
Paylaş:
M

Yazar

Mahmut Sarıkaya

yazılım Geliştirici

Yorumlar

Henüz yorum yok. İlk yorumu siz yapın!

Yorum Bırakın

8 + 2 =