
September 11, 2026
12 min read
By Kokil Thapa | Last reviewed: September 2026
URL Rewrite and ARR on IIS turn a Windows web server into a capable reverse proxy and load balancer. Most teams reach for Nginx or Apache on Linux first. Corporate networks, legacy .NET estates, and mixed Windows/Linux shops often keep IIS at the edge instead. If you need clean URLs, HTTPS enforcement, or traffic split across PHP and Laravel backends, the combination of the IIS URL Rewrite Module and Application Request Routing (ARR) is the standard path on Windows Server.
What is URL Rewrite and ARR on IIS, and when do you need both?
URL Rewrite is an IIS extension that rewrites, redirects, or blocks requests based on patterns you define. ARR sits one layer above the backend and handles reverse proxying, health checks, and load balancing across a server farm.
You need both when IIS terminates TLS and forwards traffic to Linux or Windows app servers behind it. A single URL Rewrite rule can redirect HTTP to HTTPS. ARR handles the actual proxy hop to http://10.0.1.20 or a three-node farm.
Common scenarios I see on migration and hybrid-hosting projects:
- Reverse proxy from IIS to a Laravel application running on Ubuntu with Apache or Nginx.
- Load balancing two or more identical PHP-FPM nodes during a website migration.
- Canonical host redirects (
wwwto bare domain, or the reverse). - Path-based routing:
/apito one backend, everything else to another. - Staging environments where IIS fronts production-like traffic without exposing internal IPs.
URL Rewrite alone handles redirects and internal rewrites within the same site. ARR alone cannot match complex URL patterns without Rewrite. Together they replace much of what Nginx proxy_pass and rewrite directives do on Linux.
How do you install URL Rewrite and ARR on IIS?
Install both modules before writing any rules. Missing ARR is the most common reason a rewrite rule silently fails to proxy.
Step 1: Install URL Rewrite Module 2
Download the URL Rewrite Module from Microsoft or use Web Platform Installer. After installation, open IIS Manager. You should see a URL Rewrite icon on every site and at the server level.
Step 2: Install Application Request Routing 3.0
ARR 3.0 depends on URL Rewrite and the Web Farm Framework. Install ARR, then confirm the Application Request Routing Cache icon appears at the server node in IIS Manager.
Step 3: Enable the proxy at server level
ARR ships with the proxy disabled. Enable it once at the server root:
- Open IIS Manager and click the server name, not a site.
- Double-click Application Request Routing Cache.
- Click Server Proxy Settings in the Actions pane.
- Check Enable proxy and apply.
Without this step, inbound rewrite actions of type Rewrite pointing to an external URL return HTTP 502 or do nothing useful. I have seen teams debug web.config for hours while the proxy toggle stayed off.
Step 4: Verify modules loaded
Run this in an elevated PowerShell session:
Get-WebGlobalModule | Where-Object { $_.Name -match 'Rewrite|ARR|Proxy' } You should see RewriteModule and ARR-related modules listed. If either is missing, restart IIS with iisreset after reinstalling.
For a full IIS baseline, see the companion guide on hosting PHP on IIS. That walkthrough covers FastCGI and handler mappings this article assumes you can reach from a proxied backend.
How do you configure a reverse proxy with URL Rewrite and ARR on IIS?
The typical pattern is an inbound rule that matches all traffic and rewrites to a backend URL. ARR forwards the request and returns the response to the client.
Basic reverse proxy web.config
Place this in the site root web.config when IIS fronts a single Laravel or PHP backend:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="ReverseProxyToBackend" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://10.0.1.20/{R:1}" />
<serverVariables>
<set name="HTTP_X_FORWARDED_PROTO" value="https" />
<set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
<set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
<set name="HTTP_ACCEPT_ENCODING" value="" />
</serverVariables>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration> Several details matter here. Clearing Accept-Encoding prevents double-compression bugs when ARR decompresses an upstream gzip response and IIS compresses again. Setting X-Forwarded-Proto lets Laravel generate correct HTTPS URLs when TLS stops at IIS.
Allow server variables
IIS blocks custom server variables until you whitelist them. At the server level in URL Rewrite, open View Server Variables and add:
HTTP_X_FORWARDED_PROTOHTTP_X_FORWARDED_HOSTHTTP_X_ORIGINAL_ACCEPT_ENCODINGHTTP_ACCEPT_ENCODING
Skip this step and IIS returns HTTP 500.12 with a server-variable error in the failed-request trace.
Trust proxies in Laravel
On the Laravel backend, configure trusted proxies so Request::secure() and signed URLs work:
/* bootstrap/app.php or TrustProxies middleware */
->withMiddleware(function (Middleware $middleware) {
$middleware->trustProxies(at: '*', headers: Request::HEADER_X_FORWARDED_ALL);
}) Signed and temporary links break without this. See Laravel signed URLs for temporary access for how proxy misconfiguration surfaces in production.
HTTPS redirect rule
Add a separate inbound rule above the proxy rule. It redirects plain HTTP to HTTPS:
<rule name="Force HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule> Order matters. Put redirect rules first, then proxy rules. Test patterns with a regex tester before deploying to production.
How do you set up ARR server farms and load balancing on IIS?
When you have more than one backend, create an ARR server farm instead of hard-coding an IP in web.config. IIS handles health probes and distributes requests.
Create a server farm
- In IIS Manager, click the server node.
- Open Server Farms and click Create Server Farm.
- Name the farm (for example
laravel-backend). - Add server addresses and ports. Use internal IPs, not public DNS names.
- Choose a load-balancing algorithm. Round Robin is the default.
- Enable health checks against a probe URL like
/health.
Point your rewrite rule at the farm using the special syntax:
<action type="Rewrite" url="http://laravel-backend/{R:1}" /> ARR resolves laravel-backend to the farm members you defined. Unhealthy nodes drop out automatically when probes fail.
| Feature | URL Rewrite alone | URL Rewrite + ARR |
|---|---|---|
| HTTP to HTTPS redirect | Yes | Yes |
| Reverse proxy to one backend | Yes (with ARR proxy enabled) | Yes |
| Load balancing | No | Yes (server farms) |
| Health-based failover | No | Yes |
| Response caching at edge | No | Yes (ARR cache) |
| Sticky sessions (affinity) | No | Yes |
For high-traffic Laravel apps, pair ARR with Redis session storage on the backend. Sticky sessions at the IIS layer are a fallback, not a substitute for shared session state. See API rate limiting and abuse prevention for edge-layer throttling patterns that complement ARR.
What are the common URL Rewrite and ARR on IIS mistakes in production?
Most failures are configuration order, missing headers, or proxy settings — not ARR itself.
Lost client IP addresses
Backend logs show every request from the IIS server IP. Fix it by preserving the original IP in ARR:
- Server node → Application Request Routing Cache → Server Proxy Settings.
- Check Preserve client IP in the following header.
- Set the header name to
X-Forwarded-For.
Configure your Laravel or Apache backend to read X-Forwarded-For for logging and rate limiting.
Infinite redirect loops
Loops happen when the backend also redirects HTTP to HTTPS, but IIS already terminated TLS. The backend sees HTTP, redirects to HTTPS, and the cycle repeats.
Fix: set X-Forwarded-Proto: https in the rewrite rule and trust it on the backend. Do not run a second HTTPS redirect behind the proxy unless you intentionally terminate TLS twice.
502 Bad Gateway after deploy
Check these in order:
- ARR proxy enabled at server level.
- Backend firewall allows inbound from the IIS server IP.
- Backend binding listens on the correct port.
- Server variables whitelisted.
- No stale DNS if the farm uses hostnames.
Enable Failed Request Tracing in IIS for status code 502. The trace pinpoints whether Rewrite or ARR failed. For ongoing monitoring, support and maintenance contracts often include IIS and Linux edge debugging together.
WebSocket and long-polling failures
ARR supports WebSockets, but you must enable the protocol on the site. In IIS Manager, open the site → Configuration Editor → system.webServer/webSocket → set enabled to True.
Livewire and Laravel Echo websocket connections fail silently when this setting is off. Increase ARR timeout values for long-running requests on reporting or export endpoints.
Outbound rewrite rules
Outbound rules transform response HTML — useful when a legacy app emits absolute http:// links. Define them in the same web.config under <outboundRules>. Test carefully; aggressive outbound rewriting breaks JSON API responses.
Validate outbound patterns with sample response bodies using a JSON formatter when APIs are in the path.
How does URL Rewrite and ARR on IIS compare to Nginx and Apache on Linux?
My daily production work runs on Ubuntu with Apache or Nginx and PHP-FPM 8.3/8.4. IIS with URL Rewrite and ARR is the right tool when Windows Server is already mandated or when a .NET and PHP hybrid must share one edge.
Nginx reverse proxy config is shorter:
location / {
proxy_pass http://10.0.1.20;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
} ARR plus URL Rewrite reaches the same outcome with more GUI surface area and XML in web.config. The operational model differs, not the HTTP semantics.
For greenfield Laravel 13 on PHP 8.3+, Linux with Nginx or Apache remains my default recommendation. IIS plus ARR wins when compliance, licensing, or existing Windows ops teams block a Linux edge. On a legal-tech portal project, the app ran on Laravel while the corporate edge stayed on IIS — ARR bridged the gap without rewriting either layer.
Projects like Adventure Third Pole Trek and Mijar Law Associates run on Linux stacks in production. The IIS patterns here apply when those same apps sit behind a Windows corporate reverse proxy during migration or hybrid hosting.
Reference documentation: Microsoft URL Rewrite Module docs and ARR planning guide. For Apache equivalents, see the Apache mod_proxy documentation.
Additional internal resources: building a URL shortener system design, Linux system administration, domain and hosting setup, testing and optimization, speed optimization, Ansible playbooks for PHP provisioning, and technical SEO for canonical URL rules at the edge.
Key Takeaways
- Install URL Rewrite and ARR, then enable the ARR proxy at the server level before any rewrite rules will forward traffic.
- Whitelist server variables (
X-Forwarded-Proto,X-Forwarded-For) and trust proxies on Laravel backends. - Place HTTPS redirect rules above proxy rules; clear
Accept-Encodingto prevent double compression. - Use ARR server farms with health probes for load balancing instead of hard-coded single IPs in production.
- Enable WebSockets on the IIS site when proxying Livewire, Echo, or other persistent connections.
- Validate with Failed Request Tracing and
curl -Ibefore cutover during a migration window.
People Also Ask
Can URL Rewrite on IIS work without ARR?
Yes, for redirects and internal rewrites within the same IIS site. Reverse proxying to external backends requires ARR with the server-level proxy enabled. URL Rewrite alone cannot forward requests to another server.
Does ARR support SSL offloading to Laravel backends?
Yes. Terminate TLS on IIS with a certificate bound to the site. Forward plain HTTP to internal backends on a private network. Set X-Forwarded-Proto: https so Laravel generates correct URLs and cookies.
How do you debug a 502 Bad Gateway from ARR?
Enable Failed Request Tracing for 502 on the IIS site. Confirm ARR proxy is enabled, the backend is reachable from the IIS server, firewall rules allow the hop, and server variables are whitelisted. Test the backend directly with curl from the IIS machine.
Is ARR suitable for high-traffic production load balancing?
ARR handles moderate to high traffic for many enterprise deployments. Very high-scale scenarios often move to dedicated load balancers or Nginx/HAProxy on Linux. ARR fits well when Windows infrastructure is fixed and backend pools are modest.
Deploy URL Rewrite and ARR on IIS with confidence
URL Rewrite and ARR on IIS give you a production-grade reverse proxy on Windows Server when Linux at the edge is not an option. Install both modules, enable the proxy, whitelist forwarded headers, and point inbound rules at a server farm with health checks. Match what your Laravel or PHP backend expects — trusted proxies, correct scheme headers, and WebSocket support — and the setup behaves like Nginx behind the scenes.
If you are migrating from IIS to Linux or need a hybrid edge configured and tested, contact us or review our website migration service. For greenfield apps, explore custom software development on the stack that fits your ops team.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

