YARP (Yet Another Reverse Proxy) is Microsoft's library for building high-performance reverse proxies in .NET. Unlike Nginx or HAProxy, YARP runs inside your ASP.NET Core application, giving you full access to the .NET middleware pipeline for routing, authentication, rate limiting, and request transformation.

Setup

dotnet add package Yarp.ReverseProxy

Configure in Program.cs:

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

var app = builder.Build();

app.MapReverseProxy();

app.Run();

Configuration

Define routes and clusters in appsettings.json:

appsettings.json
{
  "ReverseProxy": {
    "Routes": {
      "api-route": {
        "ClusterId": "api-cluster",
        "Match": {
          "Path": "/api/{**catch-all}"
        }
      },
      "web-route": {
        "ClusterId": "web-cluster",
        "Match": {
          "Path": "/{**catch-all}"
        }
      }
    },
    "Clusters": {
      "api-cluster": {
        "Destinations": {
          "api-1": { "Address": "https://api-server-1:5001" },
          "api-2": { "Address": "https://api-server-2:5001" }
        },
        "LoadBalancingPolicy": "RoundRobin"
      },
      "web-cluster": {
        "Destinations": {
          "web-1": { "Address": "https://web-server:5002" }
        }
      }
    }
  }
}

Routes match incoming requests by path (and optionally by host, headers, or query parameters). Each route points to a cluster, which contains one or more destination addresses.

Load Balancing Policies

YARP supports several built-in policies:

data.json
{
  "api-cluster": {
    "LoadBalancingPolicy": "LeastRequests",
    "Destinations": {
      "api-1": { "Address": "https://server-1:5001" },
      "api-2": { "Address": "https://server-2:5001" },
      "api-3": { "Address": "https://server-3:5001" }
    }
  }
}

Request Transforms

Modify requests as they pass through the proxy:

data.json
{
  "api-route": {
    "ClusterId": "api-cluster",
    "Match": { "Path": "/api/{**remainder}" },
    "Transforms": [
      { "PathRemovePrefix": "/api" },
      { "RequestHeader": "X-Forwarded-Prefix", "Set": "/api" }
    ]
  }
}

For complex transforms, use code:

Example.cs
builder.Services.AddReverseProxy()
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
    .AddTransforms(context =>
    {
        context.AddRequestTransform(async transformContext =>
        {
            var token = await GetAccessTokenAsync();
            transformContext.ProxyRequest.Headers.Authorization =
                new AuthenticationHeaderValue("Bearer", token);
        });
    });

This injects a bearer token into every proxied request — useful for backend-to-backend authentication.

Health Checks

Configure active health probes:

data.json
{
  "api-cluster": {
    "HealthCheck": {
      "Active": {
        "Enabled": true,
        "Interval": "00:00:30",
        "Timeout": "00:00:10",
        "Path": "/health"
      }
    },
    "Destinations": {
      "api-1": { "Address": "https://server-1:5001" }
    }
  }
}

YARP periodically calls /health on each destination. Unhealthy destinations are removed from rotation until they recover.

Programmatic Configuration

For dynamic scenarios, load configuration from code instead of JSON:

Example.cs
builder.Services.AddReverseProxy()
    .LoadFromMemory(GetRoutes(), GetClusters());

RouteConfig[] GetRoutes() =>
[
    new RouteConfig
    {
        RouteId = "api-route",
        ClusterId = "api-cluster",
        Match = new RouteMatch { Path = "/api/{**catch-all}" }
    }
];

ClusterConfig[] GetClusters() =>
[
    new ClusterConfig
    {
        ClusterId = "api-cluster",
        LoadBalancingPolicy = "RoundRobin",
        Destinations = new Dictionary<string, DestinationConfig>
        {
            ["api-1"] = new() { Address = "https://server-1:5001" },
            ["api-2"] = new() { Address = "https://server-2:5001" }
        }
    }
];

Middleware Integration

Because YARP runs inside ASP.NET Core, you can apply any middleware:

Example.cs
app.UseAuthentication();
app.UseAuthorization();
app.UseRateLimiter();

app.MapReverseProxy(proxyPipeline =>
{
    proxyPipeline.UseSessionAffinity();
    proxyPipeline.UseLoadBalancing();
    proxyPipeline.UsePassiveHealthChecks();
});

This applies authentication and rate limiting before the proxy, then uses YARP's own middleware for session affinity and load balancing.

Use Cases

YARP works well as an API gateway, a BFF (backend for frontend), a migration tool for gradually routing traffic from an old system to a new one, or a development proxy for aggregating multiple microservices behind a single endpoint. Because it's just .NET code, you can add custom logic that would require plugins or scripting in traditional reverse proxies.