What Is Application Request Routing?

Application Request Routing (ARR) is a Microsoft IIS extension that turns a Windows Server 2022 machine into a capable HTTP load balancer and reverse proxy. It works in conjunction with the URL Rewrite Module to intercept requests, evaluate server farm configurations, and forward traffic to one or more backend servers. ARR is widely used in on-premises deployments to distribute load across web application servers, provide high availability, offload SSL termination, and cache static content on disk — all without third-party load balancer hardware.

ARR operates at the HTTP layer, making routing decisions based on request properties rather than raw TCP connections. This means it can route based on URL, host header, or cookie value, and it integrates cleanly with IIS site bindings and authentication.

Installing ARR on Windows Server 2022

ARR depends on the URL Rewrite Module. Install URL Rewrite first if you have not already done so. Then download and install ARR:

# Download ARR 3.0 x64
Invoke-WebRequest -Uri "https://download.microsoft.com/download/A/A/5/AA548B01-E30D-4F77-862A-1EA3F17A7EC2/ARRv3_0_amd64_EN-US.msi" -OutFile "C:Temparr_amd64.msi"

# Silent install
Start-Process msiexec.exe -ArgumentList "/i C:Temparr_amd64.msi /quiet /norestart" -Wait

# Restart IIS
iisreset /restart

Confirm ARR is installed by checking for the ApplicationRequestRouting module in IIS:

Get-WebConfiguration system.webServer/globalModules | Where-Object { $_.name -like "*ApplicationRequestRouting*" }

After installation, a new node labelled Server Farms appears in IIS Manager under the server root. This is where all ARR server farm configuration lives.

Enabling ARR as a Proxy

Before ARR can forward requests, the proxy feature must be enabled at the server level. This is a one-time setting that is off by default:

# Enable the ARR proxy
Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "system.webServer/proxy" `
  -name "enabled" -value "true"

You can also enable it through IIS Manager: click the server node, open Application Request Routing Cache, then click Server Proxy Settings in the Actions panel and check Enable proxy.

Creating a Server Farm

A server farm is a named group of backend servers that ARR routes traffic to. Each server in the farm represents an application server instance. Create a server farm via PowerShell:

# Create a server farm named "MyAppFarm"
Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms" `
  -name "." `
  -value @{name="MyAppFarm"; enabled="true"}

Add backend servers to the farm:

# Add server 1
Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms/webFarm[@name='MyAppFarm']/server" `
  -name "." `
  -value @{address="192.168.1.101"; enabled="true"}

# Add server 2
Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms/webFarm[@name='MyAppFarm']/server" `
  -name "." `
  -value @{address="192.168.1.102"; enabled="true"}

Each server entry can also specify a port (default 80) and a weight for weighted load balancing. When the server farm is created through the IIS Manager wizard, it automatically offers to create the URL Rewrite rules needed to route traffic through it.

Health Test Configuration

ARR continuously monitors backend server health using HTTP probes. Configure health tests so that ARR automatically removes unresponsive servers from rotation:

# Set health test URL and interval
Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms/webFarm[@name='MyAppFarm']/applicationRequestRouting/healthCheck" `
  -name "url" -value "http://192.168.1.101/health"

Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms/webFarm[@name='MyAppFarm']/applicationRequestRouting/healthCheck" `
  -name "interval" -value "00:00:30"

Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms/webFarm[@name='MyAppFarm']/applicationRequestRouting/healthCheck" `
  -name "responseMatch" -value "OK"

The health check URL should return a 200 status and (optionally) a body string that ARR can match against the responseMatch property. If a server fails the health test, ARR marks it unhealthy and stops sending new requests to it. When the server recovers and passes the next probe, it is automatically re-added to rotation. Set the interval and timeout to values appropriate for your environment — a 30-second interval with a 10-second timeout is a reasonable starting point.

Load Balancing Algorithms

ARR supports several load balancing algorithms, configured per server farm:

Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms/webFarm[@name='MyAppFarm']/applicationRequestRouting/loadBalancing" `
  -name "algorithm" -value "RoundRobin"

Available algorithm values:

RoundRobin              - Distributes requests evenly in order (default)
WeightedRoundRobin      - Distributes proportionally based on server weight
LeastCurrentRequest     - Sends to the server with fewest active connections
LeastResponseTime       - Sends to the server with the lowest average response time
WeightedTotalTraffic    - Routes by total traffic volume, weighted
ServerVariable          - Routes based on a named server variable value

For most web applications with roughly equal server capacity, LeastCurrentRequest provides the most even distribution under variable load. RoundRobin works well when request processing times are uniform.

To set server weights for WeightedRoundRobin:

Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms/webFarm[@name='MyAppFarm']/server[@address='192.168.1.101']" `
  -name "weight" -value "100"

Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms/webFarm[@name='MyAppFarm']/server[@address='192.168.1.102']" `
  -name "weight" -value "50"

In this example, server 101 receives twice the traffic of server 102, useful when servers have different hardware capabilities.

Configuring ARR as a Reverse Proxy with URL Rewrite

ARR uses URL Rewrite rules to determine when to proxy a request and to which farm. The IIS Manager wizard creates these rules automatically when you create a server farm, but you can also write them manually for fine-grained control:


  
    
      
        
        
      
    
  

When the URL Rewrite target host matches a server farm name, ARR intercepts the rewritten request and applies load balancing logic to forward it to one of the farm’s backend servers. The farm name in the URL acts as an ARR routing directive.

To proxy only a specific URL prefix (e.g., /api/) to a farm while serving other requests locally:


  
  

Session Affinity (Sticky Sessions)

Some applications store session state in server memory and require that a client always reaches the same backend server. ARR implements session affinity using a cookie. Enable it on the server farm:

Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms/webFarm[@name='MyAppFarm']/applicationRequestRouting" `
  -name "affinity.useCookie" -value "true"

Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "webFarms/webFarm[@name='MyAppFarm']/applicationRequestRouting" `
  -name "affinity.cookieName" -value "ARRAffinity"

When affinity is enabled, ARR sets an ARRAffinity cookie in the response after the first request. Subsequent requests from the same client include this cookie, and ARR uses it to route the request to the same backend server. Note that sticky sessions reduce the effectiveness of load balancing and should only be used when the application cannot be refactored to use a shared session store (such as Redis or SQL Server).

ARR Offloading and SSL Termination

ARR can terminate TLS at the proxy layer, forwarding plain HTTP to backend servers. This offloads the TLS handshake and encryption overhead from application servers. To configure SSL offloading, bind the HTTPS certificate to the ARR proxy site and configure backend servers to listen on HTTP only. Add a server variable to let backends know the original protocol:


  
    
      
      
        
      
      
        
      
      
    
  
  
    
  

Backend applications should inspect the X-Forwarded-Proto header to determine whether the original client request was HTTP or HTTPS.

Disk-Based Output Caching with ARR

ARR can cache responses from backend servers to disk, significantly reducing backend load for cacheable content. Enable caching in ARR cache settings:

# Enable disk cache
Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "system.webServer/diskCache" `
  -name "enabled" -value "true"

# Set cache directory and size limit (bytes)
Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "system.webServer/diskCache" `
  -name "path" -value "D:ARRCache"

Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" `
  -filter "system.webServer/diskCache" `
  -name "maxSize" -value "10240"

ARR respects standard HTTP caching headers (Cache-Control, Expires, Pragma) when deciding what to cache. Responses with Cache-Control: no-store or those containing Set-Cookie headers are not cached. For maximum effectiveness, ensure backend servers emit appropriate Cache-Control: max-age=N headers on static resources.

Monitoring ARR

ARR exposes runtime statistics through IIS Manager under the server farm’s Monitoring and Management node. You can see per-server request counts, bytes transferred, current connections, and health status. For scripted monitoring, query the ARR performance counters:

# List ARR-related performance counters
Get-Counter -ListSet "Application Request Routing" | Select-Object -ExpandProperty Counter

# Sample current requests per second across all servers
Get-Counter "Application Request Routing(*)Requests/Sec" -SampleInterval 5 -MaxSamples 3

For production environments, integrate these counters into your monitoring platform (PRTG, Zabbix, Azure Monitor, etc.) to alert on elevated error rates or server health failures. Track the Failed Requests/Sec and 502 Errors/Sec counters particularly closely — a spike in 502s typically indicates backend servers are unreachable or overloaded.