Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Host PHP on IIS

By Kokil Thapa | Last reviewed: August 2026

If you need to host PHP on IIS for a Windows Server environment, the only production-viable method today is FastCGI via the Web Platform Installer or manual binary mapping. Legacy ISAPI filters are obsolete and insecure. This guide walks through configuring PHP 8.4 on IIS 10/11 with correct handler mappings, OPcache tuning, and URL rewriting so your Laravel, WordPress, or custom application runs reliably without the performance penalties that plague default installations.

How Do You Install and Configure PHP to Host PHP on IIS?

The most common mistake when setting out to host PHP on IIS is downloading the wrong PHP build or using the deprecated Web Platform Installer feed that still points to EOL versions. In 2026, you should manually download the current stable Non-Thread Safe (NTS) x64 zip from windows.php.net. Thread-safe builds add unnecessary overhead because IIS FastCGI manages process isolation itself; NTS is faster and the recommended standard.

Client BrowserHTTP RequestIIS Web ServerURL RewriteFastCGI ModuleStatic FilesPHP-CGI.exeWorker Process PoolOPcache EnabledMySQL /Redis
Request flow when you host PHP on IIS: IIS routes dynamic requests via FastCGI to a pool of php-cgi worker processes while serving static assets directly.

Download and Extract the Correct Build

  1. Navigate to windows.php.net/download and select VS16 x64 Non Thread Safe for PHP 8.4 (or 8.3 LTS).
  2. Extract to C:\php. Avoid paths with spaces; they cause silent failures in handler mappings.
  3. Rename php.ini-development to php.ini. Never use the production template unmodified—it disables error display but also sets restrictive defaults unsuitable for initial debugging.
  4. Add C:\php to your system PATH so CLI commands like php artisan or composer resolve correctly.

Register FastCGI in IIS

Open IIS Manager, select the server node, and open Handler Mappings. Add a new Module Mapping:

  • Request path: *.php
  • Module: FastCgiModule
  • Executable: C:\php\php-cgi.exe
  • Name: PHP_via_FastCGI

Click "Request Restrictions", go to the "Mapping" tab, and ensure "Invoke handler only if request is mapped to:" is unchecked. Without this, POST requests and framework routing often return 404s.

What Are the Critical php.ini Settings When You Host PHP on IIS?

Default php.ini values assume Apache mod_php semantics. On IIS FastCGI, misconfigured directives cause intermittent 500 errors, slow page loads, or file upload failures. These are the settings I verify on every production deployment.

; Performance & Stability
max_execution_time = 300
memory_limit = 256M
post_max_size = 64M
upload_max_filesize = 64M
realpath_cache_size = 4096K
realpath_cache_ttl = 600

; OPcache (mandatory for production)
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.revalidate_freq=0

; Session handling (avoid file locking on NTFS)
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?database=0"

; Error handling
display_errors = Off
log_errors = On
error_log = C:\inetpub\logs\php-errors.log

OPcache is non-negotiable. Without it, PHP recompiles every script on each request. With validate_timestamps=0, you gain 3–5x throughput. The tradeoff is that code changes require an explicit cache clear—either recycle the application pool or call opcache_reset() via a deploy hook. On my legal-tech portals running on shared EC2 infrastructure, disabling timestamp validation reduced average response time from 320ms to 85ms under load.

Session storage matters more on Windows than Linux. NTFS file locking causes session contention under concurrent requests. Redis eliminates this bottleneck entirely. If Redis isn't available, use SQL Server or PostgreSQL session drivers instead of the default file handler.

ISAPI (Deprecated)❌ Loads into w3wp.exe❌ No process isolation❌ Crash kills site❌ No PHP 8.x support❌ Security riskDO NOT USECGI (Legacy)⚠️ Spawns new process⚠️ High startup overhead⚠️ Poor concurrency✅ Process isolation✅ Works but slowAVOID IN PRODFastCGI (Correct)✅ Persistent workers✅ Low latency✅ Process isolation✅ OPcache compatible✅ PHP 8.4 supportedPRODUCTION STD
Execution mode comparison when you host PHP on IIS: FastCGI provides persistent worker pools with full isolation, unlike deprecated ISAPI or inefficient CGI.

How Do You Configure URL Rewriting for Laravel and WordPress on IIS?

IIS doesn't read .htaccess files. Frameworks like Laravel and WordPress depend on clean URLs, which requires the URL Rewrite 2.1+ module. Install it via Microsoft's official download center or Chocolatey (choco install urlrewrite). After installation, create a web.config in your site root.

Laravel web.config Template

<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Laravel" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="false" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          </conditions>
          <action type="Rewrite" url="index.php/{R:1}" appendQueryString="true" />
        </rule>
      </rules>
    </rewrite>
    <staticContent>
      <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
    </staticContent>
  </system.webServer>
</configuration>

Critical detail: Set your Laravel public directory as the IIS site physical path—not the project root. Pointing IIS at C:\sites\myapp instead of C:\sites\myapp\public exposes .env, storage/, and vendor files. This is the #1 security vulnerability I audit on client sites migrated from Apache.

WordPress generates its own web.config when you save permalink settings, but only if the site root is writable by the IIS_IUSRS group. If auto-generation fails, manually add the standard WordPress rewrite rule block. Always verify pretty permalinks work before going live; broken internal links destroy technical SEO foundations.

How Do You Secure and Optimize PHP on IIS for Production?

Security and performance aren't afterthoughts—they're configuration decisions made during setup. Here's what separates a fragile dev box from a resilient production host.

Configuration AreaDefault / InsecureProduction RecommendationImpact
PHP Version8.1 / 8.2 (EOL soon)8.4 NTS x64Security patches + JIT improvements
OPcacheDisabledEnabled, validate_timestamps=03–5x throughput increase
Session StorageFiles (NTFS)Redis or DatabaseEliminates lock contention
Error DisplayOn (dev default)Off + log_errors=OnPrevents info leakage
Upload Limits2MB / 8MB64MB+ based on app needsPrevents user-facing failures
FastCGI Max InstancesAuto (often too low)2–4 per CPU coreHandles traffic spikes
TLS VersionTLS 1.0/1.1 enabledTLS 1.2+ onlyPCI/DPA compliance

FastCGI Process Tuning

In IIS Manager → FastCGI Settings → Edit your PHP entry, adjust these values:

  • Max Instances: Set to 2× CPU cores for compute-bound apps, 4× for I/O-bound. Monitor with Performance Monitor → FastCGI\Active Requests.
  • Instance Max Requests: 10000. Recycles workers before memory fragmentation degrades performance.
  • Activity Timeout: 300 seconds (matches max_execution_time). Mismatches cause mysterious 500 errors mid-request.
  • Request Timeout: 310 seconds (slightly higher than activity timeout to allow graceful shutdown).
HTTP 500 ErrorCheck PHP Error Log FirstLog Has PHP ErrorLog Empty / No EntryFix Code / Config(Missing ext, syntax,memory_limit, etc.)Check IIS-Level Issues• Handler mapping path• App Pool identity permsTest & Verify FixRecycle App Pool
Troubleshooting decision tree for 500 errors when you host PHP on IIS: always check the PHP error log before investigating IIS-level configuration issues.

File Permissions That Actually Work

IIS runs under IIS_IUSRS by default. Your PHP application needs write access to specific directories only—not the entire site root. Grant modify permissions to:

  • storage/ and bootstrap/cache/ (Laravel)
  • wp-content/uploads/ and wp-content/cache/ (WordPress)
  • Custom upload/log directories defined in your app

Never grant write access to the application root or vendor/. Use icacls from an elevated prompt for precise control:

icacls "C:\sites\myapp\storage" /grant "IIS_IUSRS:(OI)(CI)M" /T
icacls "C:\sites\myapp\bootstrap\cache" /grant "IIS_IUSRS:(OI)(CI)M" /T

Monitoring and Validation

Create a health.php endpoint (protected by IP whitelist or auth) that outputs phpinfo() and OPcache status. After deployment, verify:

  • OPcache shows "Cache Full: false" and high hit rate (>95%)
  • Loaded extensions include opcache, pdo_mysql/pdo_pgsql, mbstring, openssl, curl
  • $_SERVER['SCRIPT_NAME'] reflects correct path (framework routing depends on this)
  • No "Unable to open" warnings in PHP error log

For ongoing monitoring, integrate Windows Performance Monitor counters for FastCGI active requests and queue length with your existing observability stack. If you're managing multiple client sites, consider whether a DevOps automation approach would reduce manual configuration drift across servers.

Deploying and Maintaining PHP Applications on IIS

Once you successfully host PHP on IIS, operational discipline prevents regression. Deployments should follow the same zero-downtime principles used on Linux: atomic symlink swaps, pre-warmed OPcache, and automated health checks. While Deployer and Envoy are Linux-native, PowerShell scripts or MSDeploy can replicate the workflow on Windows.

After each deploy, recycle the application pool to invalidate OPcache cleanly:

Import-Module WebAdministration
Restart-WebAppPool -Name "MyAppPool"

Never edit php.ini on a live server without testing in staging first. Configuration changes require an app pool recycle to take effect, and syntax errors will take down all sites sharing that pool. For teams managing hosted client sites, maintain separate app pools per tenant to isolate failures.

Keep PHP updated. Subscribe to the PHP Windows release RSS feed or use Chocolatey (choco upgrade php) for patch management. Security releases for Windows builds sometimes lag Linux by 24–48 hours; plan maintenance windows accordingly. Test every minor version upgrade against your application's test suite before production rollout—Windows-specific edge cases in filesystem handling and locale functions do surface between versions.

Next Steps After You Host PHP on IIS Successfully

Getting PHP running on IIS is the foundation, not the finish line. From here, focus on three priorities: benchmark your application under realistic load using tools like k6 or wrk targeting your Windows host, implement structured logging that feeds into your existing monitoring (ELK, Datadog, or even Windows Event Log forwarding), and document your exact configuration in version-controlled infrastructure-as-code templates. If you're evaluating whether IIS is the right long-term platform versus migrating to Linux, or need help optimizing an existing Windows-hosted PHP application, reach out to discuss your specific architecture.

Frequently Asked Questions

Use FastCGI with PHP 8.3 or 8.4 via the Web Platform Installer or manual zip extraction. Never use CGI or ISAPI modes as they are deprecated and insecure.

Windows Server licensing starts around Rs 45,000 per year (~USD 335), plus CALs. Linux alternatives are free, so choose IIS only if Active Directory or .NET integration is mandatory.

Yes, but configure URL Rewrite rules for routing and set storage/logs permissions correctly. In my experience, deployment tooling like Deployer lacks native Windows support, complicating production workflows compared to Linux environments.

Install PHP 8.3 or 8.4 for current security patches and performance. Ensure you download the Non Thread Safe x64 build specifically designed for FastCGI, not the Thread Safe Apache version.

Check NTFS permissions on the PHP installation folder and web root. The IUSR and IIS AppPool identity need read/execute access. Also verify the php-cgi.exe path in Handler Mappings matches your actual installation directory exactly.

Install the IIS URL Rewrite module and import Apache mod_rewrite rules or create web.config entries manually. For Laravel or Symfony, rewrite all non-file requests to index.php while preserving query strings and excluding static assets from processing.

FastCGI maintains persistent PHP processes, dramatically reducing startup overhead per request. Standard CGI spawns a new process for every hit, causing severe latency under load. Always use FastCGI for any production workload on Windows Server.

Uncomment zend_extension=opcache in php.ini and set opcache.enable=1, opcache.memory_consumption=256, and opcache.validate_timestamps=0 for production. Restart the application pool after changes. Without OPcache, PHP recompiles scripts on every request, killing performance.

Disable dangerous functions like exec and shell_exec in php.ini, restrict open_basedir to your web root, run each site in an isolated application pool with minimal privileges, and apply Windows Updates monthly. Never run PHP as Administrator or Local System.

Enable Failed Request Tracing to identify bottlenecks, check if OPcache is active via phpinfo(), monitor worker process memory usage, and verify database connection pooling. On client projects, I have found Windows Defender real-time scanning of PHP files often causes unexplained latency spikes.

Yes, install Git for Windows and Composer globally. However, most CI/CD tools assume Linux paths and SSH keys. I typically build artifacts on Linux runners and deploy only compiled code to IIS via WinRM or FTP to avoid toolchain friction.

Extract each version to separate directories like C:\php\8.3 and C:\php\8.4, then create distinct Handler Mappings pointing to specific php-cgi.exe binaries. Assign handlers at the site level to run different applications on different PHP versions simultaneously without conflicts.

Yes, this is a primary reason organizations choose IIS. Use the ldap extension or Windows Authentication module to validate users against AD. This enables single sign-on for internal portals without maintaining separate credential stores, which I have implemented for legal-tech client portals.

Windows lacks sendmail, so SMTP configuration in php.ini is mandatory. Specify a valid SMTP server, port, and authentication credentials. Many developers forget that IIS cannot relay mail locally like Linux postfix, causing silent failures in contact forms and notification systems.

If your stack is purely PHP with no .NET dependencies, Linux offers better tooling, lower costs, and superior community support. I recommend migration unless Active Directory integration, legacy ASP.NET coexistence, or corporate Windows-only policies make IIS a hard requirement for your organization.

Share this article

Quick Contact Options
Choose how you want to connect me: