Flask Windows Service 6-Hour Forced Restart: After NSSM Saved 11 Days, PRO Died Again

📅 September 23, 2026 ⏱️ 7 min read 🏷️ DevOps ✍️ BaccAI Team
Remember the W9 article from Sept 7? I said schtasks + watchdog bat kept Flask running 528 hours with no failure across 11 days.

Then Sept 19 a user emailed that PRO login wasn't working. I checked: PRO process was dead, watchdog bat file was gone, schtasks task was gone too.

The 11 days of "stable operation" was an illusion — the watchdog bat had been wiped by some Windows Defender scan weeks ago, I just didn't notice. Sept 23 I did one thing: trust no "automatic" mechanism, added a 6-hour forced restart fallback. Three-layer guardian: bat loop for instant recovery + schtasks 6-hour forced restart + manual one-click restart.
Sept 7 to Sept 23 Flask service timeline
Sept 7 rescue → Sept 19 silent death → Sept 23 3-layer fallback, 16 days of learning
Sept 7 NSSM fails → schtasks + bat rescues
↓ 11 days stable (the "528 hours no failure" from W9)
Sept 19 PRO dies silently (I didn't notice)
↓ User report + investigation
Sept 23 add 6-hour forced restart + bat loop + monitoring alert

1. Last Time I Thought It Was Solved, But It Wasn't

On Sept 7 I spent 3.5 hours wrestling with NSSM, finally used schtasks + watchdog bat. When writing W9 I was proud: "528 hours no failure".

Then Sept 19 Sunday afternoon, a user emailed that PRO login was broken:

Subject: PRO login broken
Content: Hi, https://www.baccpc.com:8000/login has been loading forever
      since yesterday. I'm a VIP member, please help.

I RDP'd in to check:

netstat -an | findstr ":8000"
# No output

Get-Process python
# No output

PRO Flask process was dead, and had been dead for at least 24 hours. PHD was still alive (still usable Sept 23 morning), but PRO was gone.

The "watchdog bat auto-restarts on death" from W9, assumes the bat file itself exists. Somewhere between Sept 13 and Sept 19, the watchdog bat was wiped by Windows Defender / disk cleanup / some action I don't remember. Bat gone, schtasks task even if running reports "file not found", Python never gets restarted.

I immediately checked D:\phd824 and D:\20260516\vb_bendi_v24 for the bat files:

Test-Path D:\phd824\run_phd_loop.bat
False

Test-Path D:\20260516\vb_bendi_v24\run_pro_loop.bat
False

Both bats were gone. The watchdog bat was cleaned up between Sept 19 and Sept 23 by some person or system, schtasks task though still there, but the target bat path can't be found, so when service died no one pulled it back up.

2. Why the Watchdog Rescue Isn't Reliable

W9's logic: Python dies → bat detects process exit → bat loop goes to :restart → kill all python → restart Python.

Sounds perfect, but assumes the bat itself is alive. These 3 situations break it:

  1. Bat file deleted: Windows Defender / third-party AV / disk cleanup / manual misclick
  2. Bat process killed: AV treats bat as suspicious script, or cmd.exe itself gets recycled
  3. schtasks task fails: task disabled, deleted, or bat path not found

Any one of these breaks the entire guardian. Sept 19 I hit #1 (file wiped).

3. 6-Hour Forced Restart: Trust No "Automatic"

Sept 23 I redesigned: don't rely on any bat file staying alive, let the OS layer do scheduled kill + restart.

Simple idea:

Each layer works independently, any layer fails, the others fallback.

Layer 1: Bat Loop (Desktop Version, Not on Server)

I put the bat on Desktop, not in D:\ root or next to app.py, so Windows Defender disk cleanup scans of D:\ won't reach it:

Desktop `app.py -PRO.bat`:

@echo off
setlocal
title BaccAI PRO - 6h Auto Restart

cd /d D:\20260516\vb_bendi_v24

:loop
echo [%date% %time%] PRO watchdog started...
C:\Users\Administrator\AppData\Local\Programs\Python\Python38\python.exe app.py
goto :restart

:restart
echo [%date% %time%] PRO exited, killing all python and restarting in 10s...
timeout /t 10 /nobreak >nul
taskkill /F /IM python.exe /T 2>nul
timeout /t 5 /nobreak >nul
goto :loop

Desktop `app.py - PHD.bat` (same logic, path changed to D:\phd824).

Double-click the desktop bat, a cmd window pops up. Minimize it to taskbar, don't close. Python dies → bat auto-restarts, no manual intervention needed.

Layer 2: schtasks 6-Hour Forced taskkill

Windows Task Scheduler doesn't need a bat running continuously, it's a Windows service maintained by the system. I configured 2 6-hourly scheduled tasks, every 6 hours force kill all python.exe:

schtasks /Create /TN "BaccAI_PRO_6h_restart" /TR "taskkill /F /IM python.exe /T" /SC HOURLY /MO 6 /RL HIGHEST /RU SYSTEM /F
schtasks /Create /TN "BaccAI_PHD_6h_restart" /TR "taskkill /F /IM python.exe /T" /SC HOURLY /MO 6 /RL HIGHEST /RU SYSTEM /F

Parameter explanation:

Key design: schtasks itself depends on no bat file, it's a Windows service that never gets wiped by Defender. taskkill is a Windows built-in exe, also no bat dependency.

Layer 3: Server Reboot Auto-Recovery

If the server itself reboots (Windows Update / power loss), desktop bat also gets closed. I additionally configured 2 ONSTART tasks, auto-run desktop bat 30 seconds after boot:

schtasks /Create /TN "BaccAI_PRO_OnBoot" /TR "C:\Users\Administrator\Desktop\app.py -PRO.bat" /SC ONSTART /RL HIGHEST /RU SYSTEM /F
schtasks /Create /TN "BaccAI_PHD_OnBoot" /TR "C:\Users\Administrator\Desktop\app.py - PHD.bat" /SC ONSTART /RL HIGHEST /RU SYSTEM /F

One gotcha: ONSTART runs bat in session 0 (system service session), no window shown, no stdin received (killing via Ctrl+C is awkward). But we don't need to kill, just let it run.

3-layer guardian architecture diagram
3-layer guardian: bat loop (second-level) + schtasks (hour-level) + ONSTART (day-level)

4. 6 Hours Is the Sweet Spot

Why 6 hours, not 1 hour or 24 hours?

Interval Pros Cons Best for
1 hour Dead process instantly restored 24 restarts per day, users lose login state / form data Internal tools, no UX concern
6 hours 4 per day, acceptable UX Short tasks may collide ✅ Most web services, recommended
24 hours Users barely notice Process quietly dead, 24h no recovery Must-not-interrupt services (payment / medical)

I chose 6 hours. Reasoning:

6 hours is reasoned: too short loses login state, too long doesn't rescue silently-dead processes. If your Flask users access frequently (high-frequency API), drop to 2-4 hours; if low-frequency blog, 12-24 hours works.

5. Common Pitfalls + Fixes

Pitfall 1: Bat Window Accidentally Closed

My coworker occasionally closes the cmd window by mistake, watchdog dies. Fix:

Pitfall 2: schtasks Task Disabled

Windows Update or system optimization tools may "disable" schtasks tasks. Check:

schtasks /Query /TN "BaccAI_PRO_6h_restart"

Check the "Status" column, anything other than "Ready" is a problem.

Pitfall 3: taskkill Kills Other Python Processes

My server only runs these two Flask apps, so taskkill python.exe is safe. If you have other Python programs, filter by window title:

taskkill /F /FI "WINDOWTITLE eq BaccAI*" /T

Only kills windows with BaccAI in title.

Pitfall 4: Slow Model Loading

PRO's LSTM model loading takes 5-10 seconds, plus DB connection pool init, total 15-20 seconds. If user happens to be using PRO for prediction, restart loses their work.

Short-term compromise: 6 hours is short enough that user collision rate is low.

Long-term solution: Add Nginx reverse proxy, rolling restart (kill one worker, start new, kill next), zero-downtime. But cost is high, wait for W10+ traffic to justify.

6. Complete Start Card (D:\seo\START_COMMANDS.txt Updated)

Step 1: Status Check

netstat -an | findstr ":8443  :8000  :8080"
Get-Process python | Select Id, StartTime
schtasks /Query /TN "BaccAI_PRO_6h_restart"
schtasks /Query /TN "BaccAI_PHD_6h_restart"

Step 2: Start (4 Ways, Pick One)

:: Way 1: Double-click desktop bat (recommended, startup + watchdog auto-restart)
:: C:\Users\Administrator\Desktop\app.py -PRO.bat
:: C:\Users\Administrator\Desktop\app.py - PHD.bat

:: Way 2: Start-Process in background
Start-Process "C:\Users\Administrator\Desktop\app.py -PRO.bat"
Start-Process "C:\Users\Administrator\Desktop\app.py - PHD.bat"

:: Way 3: Manual one-time (for debugging)
cd /d D:\phd824
C:\Users\Administrator\AppData\Local\Programs\Python\Python38\python.exe app.py

Step 3: Emergency Restart (1 Command)

taskkill /F /IM python.exe /T
timeout /t 5 /nobreak
Start-Process "C:\Users\Administrator\Desktop\app.py -PRO.bat"
Start-Process "C:\Users\Administrator\Desktop\app.py - PHD.bat"

Step 4: 6-Hour Restart Tasks (First Deploy)

schtasks /Create /TN "BaccAI_PRO_6h_restart" /TR "taskkill /F /IM python.exe /T" /SC HOURLY /MO 6 /RL HIGHEST /RU SYSTEM /F
schtasks /Create /TN "BaccAI_PHD_6h_restart" /TR "taskkill /F /IM python.exe /T" /SC HOURLY /MO 6 /RL HIGHEST /RU SYSTEM /F
schtasks /Create /TN "BaccAI_PRO_OnBoot" /TR "C:\Users\Administrator\Desktop\app.py -PRO.bat" /SC ONSTART /RL HIGHEST /RU SYSTEM /F
schtasks /Create /TN "BaccAI_PHD_OnBoot" /TR "C:\Users\Administrator\Desktop\app.py - PHD.bat" /SC ONSTART /RL HIGHEST /RU SYSTEM /F

7. Lessons for the HCU Recovery Period

Sept 7 writing W9 I thought I found the ultimate solution, Sept 23 reality slapped me. This is actually a metaphor for the SEO recovery period:

  1. Trust no "automatic": watchdog bat looks automatic, but file gets wiped and you're done. Google's algorithm looks automatic, but June 30 put me back to zero.
  2. Multi-layer redundancy always wins: June 30 I published 47 spam articles, Google demoted me. Sept 23 I added 6-hour forced restart, replaced "automatic" with "forced + multi-layer". Site content should follow the same principle — don't rely on single source (forum / repost / AI), mix PGC + UGC + repost + video.
  3. Invisible failures are the most lethal: Sept 19 PRO died for 24 hours without me knowing. The final solution includes health check email alerts (in W9 article), combined with W10's 6-hour forced restart, I get notified whenever service dies.

FAQ

Why did watchdog bat run 11 days then PRO die?
The watchdog bat is a dead-loop daemon that should restart Python on exit. But there are 3 failure modes: 1) The bat file itself gets cleaned up (Windows Defender / disk cleanup / accidental delete), 2) The schtasks task goes Stopped for some reason, 3) Python hangs without exiting, so the bat stays stuck in :loop and never reaches :restart. What hit me on Sept 23 was 1+2 combined: bat file completely gone + schtasks task missing.
Won't 6-hour forced restart be too frequent? Lose user requests?
6 hours is my balanced number. 1) Too short (1-2 hours) interrupts users too often, loses login state and form data. 2) Too long (24+ hours) doesn't rescue silently-dead processes. 3) 6 hours = 4 restarts per day, each with 15-20 seconds downtime (taskkill + bat wait + Flask startup + model load), most users won't hit it; if they do, a refresh fixes it. After 2 days of usage, no user complaints.
Will taskkill /F /IM python.exe kill my other Python processes?
Yes. If you also run other Python programs on the same server (data scrapers / scheduled tasks / Jupyter etc.), they'll all be killed. My server only runs these two Flask apps so taskkill python.exe is safe. If you have other Python processes, switch to: taskkill /F /FI "WINDOWTITLE eq BaccAI*"
Why not use Flask's threaded=True or waitress instead?
Flask dev server's concurrency is a concern, but the root issue is process death. Even with waitress, memory leaks / deadlocks / system resource exhaustion still cause death. So we need two layers: 1) Flask itself uses waitress (production WSGI), 2) OS-level 6-hour forced restart as fallback. Both layers are necessary.
What about Flask apps with slow model loading (LSTM / PyTorch)?
PRO's LSTM model loading takes 5-10 seconds, plus DB connection pool init, total 15-20 seconds. Users will see 503 during restart window. Best fix: add Nginx/IIS reverse proxy, with backend Flask behind it returning stale cache or 'service upgrading, back in 30s' page during downtime. Or use waitress + multiple workers + rolling restart (kill one, start new, kill next) for zero-downtime.

📌 Missed the NSSM story?

🛠️ W9: NSSM 4 fails 1 success 🔐 W8: HTTPS Encryption Explained 📱 W6: Mobile browser SSL fix