How to Roll Back a Deployment from a Backup in Batch Script
When a deployment goes wrong, whether due to a broken configuration, a crashing application, or unexpected behavior, the ability to quickly roll back to the previous working state is critical. A well-prepared rollback script can restore service in seconds rather than the minutes or hours it would take to debug and fix the issue under pressure.
In this guide, we will explore how to implement deployment rollback from backups in Batch Script, covering pre-deployment backup strategies, automated rollback execution, and verification workflows.
Understanding Rollback Strategies
| Strategy | Speed | Complexity | Data Requirements |
|---|---|---|---|
| Backup Restore | Medium (file copy time) | Low | Pre-deployment backup of files |
| Blue-Green Switch | Instant (symlink change) | Medium | Two full environment copies |
| Version Archive | Medium | Low | Archived packages per version |
| Git Checkout | Fast | Low | Source control history |
This guide focuses on backup restore, the most universally applicable strategy.
Method 1: Simple Rollback from Backup Directory
@echo off
setlocal
set "app_dir=C:\WebApps\MyApp"
set "backup_dir=C:\Backups\MyApp\latest"
:: Verify Admin
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges required.
pause
exit /b 1
)
echo =============================================
echo DEPLOYMENT ROLLBACK
echo =============================================
echo.
echo App directory: %app_dir%
echo Backup source: %backup_dir%
echo.
:: Verify backup exists
if not exist "%backup_dir%\" (
echo [ERROR] Backup not found: %backup_dir%
pause
exit /b 1
)
set /p "confirm=ROLL BACK to the previous version? Type ROLLBACK: "
if /i not "%confirm%"=="ROLLBACK" (
echo [CANCELLED]
pause
exit /b 0
)
echo.
echo Rolling back...
robocopy "%backup_dir%" "%app_dir%" /mir /r:3 /w:5 /np /ndl /nfl
set "result=%errorlevel%"
if %result% leq 3 (
echo.
echo [SUCCESS] Rollback complete.
echo The application has been restored to the backup version.
) else (
echo.
echo [ERROR] Rollback failed. Exit code: %result%
)
pause
Method 2: Automated Pre-Deployment Backup and Rollback
A complete workflow that creates a backup before deployment and provides a rollback script:
@echo off
setlocal enabledelayedexpansion
:: Configuration
set "app_name=WebApp"
set "app_dir=C:\WebApps\%app_name%"
set "backup_root=C:\Backups\%app_name%"
set "deploy_source=C:\Build\Publish\%app_name%"
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Admin required.
pause
exit /b 1
)
:: Verify deploy source exists
if not exist "%deploy_source%\" (
echo [ERROR] Deploy source not found: %deploy_source%
pause
exit /b 1
)
:: Timestamp for this deployment
for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "timestamp=%dt:~0,4%%dt:~4,2%%dt:~6,2%_%dt:~8,2%%dt:~10,2%%dt:~12,2%"
set "backup_dir=%backup_root%\%timestamp%"
echo =============================================
echo DEPLOY WITH BACKUP
echo App: %app_name%
echo =============================================
echo.
:: Step 1: Create pre-deployment backup
echo [1/3] Creating backup...
if not exist "%backup_root%" mkdir "%backup_root%"
if exist "%app_dir%\" (
robocopy "%app_dir%" "%backup_dir%" /mir /r:2 /w:3 /np /ndl /nfl >nul
if !errorlevel! leq 3 (
echo Backup saved: %backup_dir%
) else (
echo [ERROR] Backup failed. Aborting deployment.
exit /b 1
)
) else (
echo No existing deployment to back up (first deploy^).
)
:: Step 2: Deploy
echo [2/3] Deploying...
robocopy "%deploy_source%" "%app_dir%" /mir /r:3 /w:5 /np /ndl /nfl >nul
set "deploy_result=!errorlevel!"
if !deploy_result! leq 3 (
echo Deployed successfully.
) else (
echo [ERROR] Deploy failed (exit code: !deploy_result!^). Auto-rolling back...
if exist "%backup_dir%\" (
robocopy "%backup_dir%" "%app_dir%" /mir /r:2 /w:3 /np /ndl /nfl >nul
if !errorlevel! leq 3 (
echo [ROLLBACK] Restored from backup.
) else (
echo [CRITICAL] Rollback also failed. Manual intervention required.
)
) else (
echo [WARNING] No backup available for rollback.
)
exit /b 1
)
:: Step 3: Generate rollback script
echo [3/3] Generating rollback script...
set "rollback_script=%backup_root%\rollback_%timestamp%.bat"
(
echo @echo off
echo echo Rolling back %app_name% to backup: %timestamp%
echo set /p "confirm=Confirm rollback? Type YES: "
echo if /i not "%%confirm%%"=="YES" exit /b 0
echo robocopy "%backup_dir%" "%app_dir%" /mir /r:3 /w:5 /np
echo if %%errorlevel%% leq 3 ^(echo [SUCCESS] Rolled back.^) else ^(echo [ERROR] Rollback failed.^)
echo pause
) > "!rollback_script!"
echo Rollback script: !rollback_script!
echo.
echo =============================================
echo DEPLOYMENT COMPLETE
echo To rollback: run rollback_%timestamp%.bat
echo =============================================
pause
Method 3: Versioned Backup Archives
Maintain a rolling archive of deployment versions:
@echo off
setlocal enabledelayedexpansion
set "app_dir=C:\WebApps\MyApp"
set "archive_dir=C:\Backups\MyApp\archive"
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Admin required.
pause
exit /b 1
)
echo =============================================
echo VERSIONED ROLLBACK
echo =============================================
echo.
:: List available backup versions
echo Available backup versions:
echo ==========================
if not exist "%archive_dir%\" (
echo No archive directory found: %archive_dir%
pause
exit /b 1
)
set "count=0"
for /f "delims=" %%D in ('dir /b /ad /o-d "%archive_dir%" 2^>nul') do (
set /a count+=1
set "bk[!count!]=%%D"
echo !count!. %%D
)
if !count!==0 (
echo No backups found.
pause
exit /b 1
)
echo.
echo 0. Cancel
set /p "choice=Select version to restore: "
if "!choice!"=="0" exit /b 0
:: Validate selection
if !choice! lss 1 (
echo [ERROR] Invalid selection.
pause
exit /b 1
)
if !choice! gtr !count! (
echo [ERROR] Invalid selection.
pause
exit /b 1
)
set "selected=!bk[%choice%]!"
set "restore_from=%archive_dir%\!selected!"
if not exist "!restore_from!\" (
echo [ERROR] Backup directory not found: !restore_from!
pause
exit /b 1
)
echo.
echo Selected: !selected!
echo Source: !restore_from!
echo Target: %app_dir%
echo.
set /p "confirm=Type ROLLBACK to proceed: "
if /i not "!confirm!"=="ROLLBACK" (
echo [CANCELLED]
pause
exit /b 0
)
:: Create backup of CURRENT state first (safety net)
for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "safety=%archive_dir%\pre-rollback_%dt:~0,4%%dt:~4,2%%dt:~6,2%_%dt:~8,2%%dt:~10,2%"
echo.
echo Creating safety backup of current state...
if exist "%app_dir%\" (
robocopy "%app_dir%" "!safety!" /mir /r:2 /w:3 /np /ndl /nfl >nul
if !errorlevel! leq 3 (
echo Safety backup saved: !safety!
) else (
echo [WARNING] Safety backup may be incomplete.
)
) else (
echo No current deployment to back up.
)
:: Perform rollback
echo Restoring...
robocopy "!restore_from!" "%app_dir%" /mir /r:3 /w:5 /np /ndl /nfl >nul
set "result=!errorlevel!"
if !result! leq 3 (
echo.
echo [SUCCESS] Rolled back to: !selected!
echo Safety backup at: !safety!
) else (
echo.
echo [ERROR] Rollback failed. Exit code: !result!
echo Current state may be inconsistent. Safety backup: !safety!
)
pause
Method 4: IIS Application Rollback
For IIS web applications, stop the site, restore, and restart:
@echo off
setlocal enabledelayedexpansion
set "site_name=MyWebApp"
set "pool_name=MyWebApp"
set "app_dir=C:\inetpub\wwwroot\MyWebApp"
set "backup_dir=C:\Backups\MyWebApp\latest"
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Admin required.
pause
exit /b 1
)
echo =============================================
echo IIS APPLICATION ROLLBACK
echo =============================================
echo.
:: Verify backup
if not exist "%backup_dir%\" (
echo [ERROR] No backup found at %backup_dir%
pause
exit /b 1
)
:: Verify appcmd exists
set "appcmd=%SystemRoot%\system32\inetsrv\appcmd.exe"
if not exist "%appcmd%" (
echo [ERROR] appcmd.exe not found. Is IIS installed?
pause
exit /b 1
)
set /p "confirm=Roll back %site_name%? Type ROLLBACK: "
if /i not "%confirm%"=="ROLLBACK" exit /b 0
:: Step 1: Stop the site and app pool
echo [1/3] Stopping IIS site and app pool...
"%appcmd%" stop site /site.name:"%site_name%" 2>nul
"%appcmd%" stop apppool /apppool.name:"%pool_name%" 2>nul
:: Wait for app pool to fully stop
echo Waiting for app pool to stop...
set /a wait=0
:wait_pool
for /f "tokens=*" %%S in ('"%appcmd%" list apppool /apppool.name:"%pool_name%" /text:state 2^>nul') do set "pool_state=%%S"
if /i "!pool_state!"=="Stopped" goto pool_stopped
set /a wait+=1
if !wait! geq 15 (
echo [WARNING] App pool did not stop within 15 seconds. Proceeding anyway.
goto pool_stopped
)
timeout /t 1 /nobreak >nul
goto wait_pool
:pool_stopped
echo Site and app pool stopped.
:: Step 2: Restore from backup
echo [2/3] Restoring files...
robocopy "%backup_dir%" "%app_dir%" /mir /r:3 /w:5 /np /ndl /nfl
set "result=%errorlevel%"
:: Step 3: Restart the site and app pool
echo [3/3] Starting IIS site and app pool...
"%appcmd%" start apppool /apppool.name:"%pool_name%"
"%appcmd%" start site /site.name:"%site_name%"
if %result% leq 3 (
echo.
echo [SUCCESS] %site_name% rolled back and restarted.
) else (
echo.
echo [WARNING] Restore may be incomplete (exit code: %result%^). Check the site.
)
pause
Method 5: Cleanup Old Backups
Prevent backup storage from growing indefinitely:
@echo off
setlocal enabledelayedexpansion
set "backup_root=C:\Backups\MyApp\archive"
set "keep=5"
if not exist "%backup_root%\" (
echo [ERROR] Backup directory not found: %backup_root%
pause
exit /b 1
)
echo Cleaning old backups (keeping newest %keep%^)...
echo.
set "count=0"
set "deleted=0"
for /f "delims=" %%D in ('dir /b /ad /o-d "%backup_root%" 2^>nul') do (
set /a count+=1
if !count! gtr %keep% (
echo Deleting: %%D
rmdir /s /q "%backup_root%\%%D"
set /a deleted+=1
) else (
echo Keeping: %%D
)
)
echo.
if !count!==0 (
echo [INFO] No backups found.
) else (
echo [DONE] Kept %keep% newest, deleted !deleted! old backup(s^).
)
pause
Common Mistakes
The Wrong Way: Rolling Back Without a Safety Backup
:: WRONG - If the rollback itself is bad, you cannot undo it
robocopy "C:\Backups\old" "C:\WebApps\Live" /mir
:: Current state is gone forever
Output Concern: Always create a backup of the current state before rolling back. If the backup you are restoring from is corrupted or is the wrong version, you lose both the current state and the ability to recover.
The Wrong Way: Rolling Back While the Application Is Running
:: WRONG - Replacing files while IIS is serving them
robocopy "C:\Backups\latest" "C:\inetpub\wwwroot\MyApp" /mir
:: Files may be locked, rollback is incomplete
Stop the application (IIS site and app pool) before replacing files. Running applications lock DLLs and configuration files, causing the rollback to fail partially.
Best Practices
- Always backup before deploying: Every deployment should create a timestamped backup first.
- Backup current state before rolling back: Create a safety net in case the rollback itself needs to be undone.
- Stop the application first: Prevent file locks by stopping IIS sites and app pools before restoring.
- Keep multiple backup versions: Maintain at least 3–5 recent backups for flexibility.
- Generate rollback scripts automatically: Each deployment should produce a one-click rollback script.
Conclusion
Rolling back a deployment from a backup in Batch Script follows a straightforward pattern: stop the application, restore the backup files using Robocopy's mirror mode, and restart the application. The critical enabler is the pre-deployment backup, which must be created reliably before every deployment. By maintaining versioned backup archives with retention policies, generating automatic rollback scripts, and always creating safety backups before restoring, administrators ensure that any deployment problem can be resolved in seconds rather than hours.