Windows Server  ·  high  ·  Roles & shared services

HTTP 503 Service Unavailable — the application pool has stopped

IIS is running but the pool that should serve the site is stopped, so http.sys answers 503 itself without ever reaching the application.

What you see

Every request to a site returns a bare 503 page. IIS Manager shows the application pool as Stopped, and starting it stops again after the next request.

What is actually wrong

Rapid-fail protection stopped the pool after repeated worker crashes, the pool identity's password has expired, or the worker cannot load .NET.

Codes and articles

503Service UnavailableEvent 5002Event 5021Event 5057rapid fail protection

Fixes (2)

Fix the pool identity
Elevated PowerShell20 minuteslow riskreversible

The pool will not start. An expired or changed service-account password is the usual reason.

  1. Read the events — 5021 is a bad identity password, 5057 a .NET load failure.

    PowerShell
    Get-WinEvent -LogName System -MaxEvents 40 | Where-Object { $_.ProviderName -like '*WAS*' -or $_.ProviderName -like '*IIS*' } | Format-List TimeCreated, Id, Message
  2. Check what identity the pool runs as.

    PowerShell
    Import-Module WebAdministrationGet-ChildItem IIS:\AppPools | ForEach-Object { [PSCustomObject]@{ Pool=$_.Name; State=$_.State; Identity=$_.processModel.identityType; User=$_.processModel.userName } } | Format-Table -AutoSize
  3. Re-enter the password for a custom identity.

    PowerShell
    Set-ItemProperty 'IIS:\AppPools\MyPool' -Name processModel.password -Value 'ThePassword'
  4. Better, move it to a group Managed Service Account so the password is never a problem again.

    PowerShell
    Set-ItemProperty 'IIS:\AppPools\MyPool' -Name processModel.identityType -Value SpecificUserSet-ItemProperty 'IIS:\AppPools\MyPool' -Name processModel.userName -Value 'EXAMPLE\svc_web$'Set-ItemProperty 'IIS:\AppPools\MyPool' -Name processModel.password -Value ''

    A gMSA's password is rotated by AD and never typed anywhere, which removes the annual outage this fault represents.

  5. Start the pool.

    PowerShell
    Start-WebAppPool -Name MyPool
Confirm it workedThe pool is Started and the site answers.
PowerShell
Get-ChildItem IIS:\AppPools | Format-Table Name, State -AutoSizeInvoke-WebRequest http://localhost/ -UseBasicParsing | Select-Object StatusCode
If you need to undo itSet the identity back to ApplicationPoolIdentity.
Stop the worker crashing and clear rapid-fail protection
Elevated PowerShell45 minutesmedium riskreversible

The pool starts then stops. Something is killing the worker process and IIS is refusing to keep restarting it.

  1. Find the crash. Event 5002 is rapid-fail protection tripping; the Application log has the actual exception.

    PowerShell
    Get-WinEvent -LogName Application -MaxEvents 30 | Where-Object { $_.Id -in 1000,1026 } | Format-List TimeCreated, Id, Message
  2. Read the rapid-fail settings — five failures in five minutes is the default and is easily hit.

    PowerShell
    Get-ItemProperty 'IIS:\AppPools\MyPool' -Name failure | Format-List rapidFailProtection, rapidFailProtectionInterval, rapidFailProtectionMaxCrashes
  3. Start the pool and watch whether it survives.

    PowerShell
    Start-WebAppPool -Name MyPoolStart-Sleep 20Get-ChildItem IIS:\AppPools | Where-Object Name -eq MyPool | Format-Table Name, State
  4. Fix the underlying crash. If it is a .NET version mismatch, confirm the runtime the pool is set to matches the application.

    PowerShell
    Get-ItemProperty 'IIS:\AppPools\MyPool' -Name managedRuntimeVersion, enable32BitAppOnWin64 | Format-List
  5. Only widen rapid-fail protection once the crash is understood — never as the fix itself.

    PowerShell
    Set-ItemProperty 'IIS:\AppPools\MyPool' -Name failure.rapidFailProtectionMaxCrashes -Value 20

    Rapid-fail protection exists to stop a broken application consuming the server. Raising the limit hides the crash and leaves the server restarting a failing worker twenty times instead of five.

Confirm it workedThe pool stays started under load and no 5002 events appear.
PowerShell
Get-WinEvent -LogName System -MaxEvents 20 | Where-Object Id -eq 5002
If you need to undo itSet rapidFailProtectionMaxCrashes back to 5.

Where this stops. This write-up was written and checked by hand. It says what each step changes, how to confirm it worked and how to reverse it, and anything destructive is flagged before you reach it. If it does not match what your machine is doing, search the Support Centre for the exact code or message — and when something needs a person, get in touch.