Auto reloading python Flask app upon code changes
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Flask provides built-in auto-reloading that restarts the development server whenever you modify Python source files. Enable it by running Flask in debug mode: set FLASK_DEBUG=1, pass debug=True to app.run(), or use the flask run --debug CLI command. Flask uses the Werkzeug reloader, which watches for file changes and automatically restarts the process. For non-Python files (templates, static assets), you may need additional configuration. Auto-reloading should only be used in development — never enable debug mode in production.
Method 1: app.run(debug=True)
debug=True enables both the auto-reloader and the interactive debugger. When you save a .py file, the server restarts automatically within a second.
Method 2: flask run --debug (Recommended)
The flask run CLI is the recommended way to start Flask applications. --debug enables both auto-reload and the debugger. --reload enables only the auto-reloader without the debugger.
Method 3: Environment Variables
Using .env files keeps debug configuration out of your source code. Flask loads .env automatically when python-dotenv is installed.
Choosing the Reloader Type
The default stat reloader polls files every second, which can be slow on large projects. The watchdog reloader uses OS-level file system events (inotify on Linux, FSEvents on macOS) for near-instant detection.
Watching Extra Files and Directories
By default, Flask only watches .py files. Template changes (Jinja2) are picked up without a restart because templates are re-rendered on each request. But configuration files and other non-Python files need extra_files.
Docker Development Setup
Volume mounting (- .:/app) maps your local source code into the container. When you edit files locally, the Flask reloader inside the container detects the changes and restarts.
Disabling Auto-Reload
Disable the reloader when debugging issues where the restart itself causes problems (e.g., database connections being dropped, or when attaching an external debugger like PyCharm or VS Code).
Common Pitfalls
- Enabling debug mode in production:
debug=Trueexposes the Werkzeug interactive debugger, which allows arbitrary Python code execution in the browser. Never deploy with debug mode enabled — it is a critical security vulnerability. Use environment variables to ensure debug mode is only active in development. - Auto-reload not detecting changes in non-.py files: Flask's reloader only watches Python files by default. Changes to templates are re-rendered per request (no restart needed), but changes to
.yaml,.json, or other config files require--extra-filesorextra_files=to be detected. - Infinite restart loop: If a syntax error occurs during import, the reloader may fail to restart cleanly. Fix the syntax error and the reloader will recover. If it does not, manually stop and restart the server.
- Port already in use after crash: If the server crashes without cleaning up, the port (5000) may remain bound. Run
lsof -i :5000(macOS/Linux) ornetstat -ano | findstr :5000(Windows) to find and kill the orphaned process. - Reloader running code twice on startup: The Werkzeug reloader spawns a child process, so top-level code outside
if __name__ == '__main__'executes twice. Put initialization code (database setup, scheduler start) inside the__name__guard or use Flask'sbefore_first_request(deprecated in 2.3+) or app factory pattern.
Summary
- Use
flask run --debugorapp.run(debug=True)to enable auto-reloading during development - Install
watchdogfor faster file change detection via OS-level events - Use
--extra-filesto watch non-Python files like config files - Never enable debug mode in production — it exposes a remote code execution vulnerability
- In Docker, mount source code as a volume for live reloading inside containers
- The reloader spawns a child process, so top-level code runs twice — use
if __name__ == '__main__'guards

