Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Reverse Proxy, API Gateway and YARP: When YARP and When Nginx or a Managed Gateway?
YARP is a reverse proxy library that lets you write your gateway as your own ASP.NET Core app; pick it when the gateway needs code-driven logic, while Nginx or an ingress fits static rules and a managed gateway fits subscriptions and a developer portal. We build Bookstore.Gateway with LoadFromConfig and MapReverseProxy and use real logs to separate the route, cluster and destination model, a gateway 404 from a backend 404, and a 502.
YARP Configuration: Route Matching, Transforms, Config from Code and Live Reload
In YARP, route order is decided first by Order, then by path, method, host, header and query specificity; path transforms map the external URL to the internal one, and X-Forwarded overwrites the client's value by default, but you have to strip internal headers yourself. Using real Bookstore.Gateway logs, we show the catch-all trap, what a broken config does on live reload, LoadFromMemory, an IProxyConfigProvider that reads SQL Server, and a per-environment IProxyConfigFilter.
Load Balancing, Health Checks and Session Affinity in YARP
In YARP, PowerOfTwoChoices and LeastRequests shift traffic away from a slow instance on their own; passive health checks only count transport errors and the reactivation period can't be shorter than the 60 second window, so use them with active checks. On three Catalog instances we measure the policies, write a zone-aware policy, and show HealthyOrPanic, HashCookie affinity, service discovery, and HTTP/2 and ActivityTimeout pitfalls with real logs.
Cross-Cutting Concerns at the Gateway: Authentication, Authorization, Rate Limiting, Timeouts and Output Caching
YARP gives a route a policy name and ASP.NET Core middleware does the work, so middleware order and a fallback authorization policy are the foundation of gateway security. With real output from Bookstore.Gateway we show JWT validation, carrying identity via the token and an internal header, per-user rate limits with 429 and Retry-After, why output caching skips requests with a token, and how a request timeout returns 400 instead of 504 in YARP 2.3 and how to fix it.
Angular BFF and Aggregation with YARP: Running Proxy Routes Side by Side with Your Own Endpoints
Because YARP routes are normal endpoints, you can serve Angular files, aggregation endpoints and proxy routes from one app on a single origin without CORS; the parts to watch are fallbacks, the timeout budget and second traffic paths. With real output from Bookstore we show a book page endpoint that calls Catalog, Inventory and Ordering in parallel, partial failure, an HttpClient that uses YARP's health data, and an IHttpForwarder that picks a target per institution.
Strangler Fig and Canary with YARP: Incremental Migration from a Legacy App and Weighted Traffic
In YARP, a strangler fig starts with a host-bound catch-all route to the old app, and every migrated page gets a more specific route; for a canary, two clusters and a small step that moves the request with ReassignProxyRequest are enough. On Bookstore's old site we change the route table phase by phase, measure a sticky 10% canary and roll back in 645 ms with a config reload.
Running YARP in Production: Observability, Performance, Containers and Multiple Instances
Under normal load YARP adds about 70 µs at the median; what matters in production is the trace passing through the gateway, alerting by error kind, per-instance rate limits and caches, the shutdown timeout and the right container image. With real output from Bookstore.Gateway we show traces with OpenTelemetry and Jaeger, the gateway's cost with k6, building a container with the SDK, YARP's nightly image and graceful shutdown.
YARP's Release History: What Changed from 1.0 to 2.3 and Reading Old Configurations
YARP 2.3 (February 2025) is still the latest release in November 2026; array routes and old policy names from pre-1.0 configs stop the app from starting, but old fields such as HttpRequest.Timeout are silently ignored. We collect the defaults that changed from 1.0 to 2.3 from the release notes, read an old config with 2.3 and its JSON schema, and move an Ocelot-based gateway to YARP, comparing both sides with the same requests.