Flask Introduction
What Flask is, how it compares to Django, and how to install it and run your first app.
What is Flask?
Flask is a lightweight WSGI web framework for Python, originally released by Armin Ronacher in 2010. Flask calls itself a microframework, but "micro" doesn't mean "toy" or "limited" — it means the core framework makes very few decisions on your behalf. There's no bundled ORM, no bundled admin panel, no bundled authentication system. Flask hands you routing, request/response handling, and template rendering, and lets you choose everything else yourself: which database library to use, which form validation approach fits, which authentication scheme makes sense for your app.
That minimalism is a deliberate design philosophy, built on two smaller libraries doing the real work under the hood:
- Werkzeug — a WSGI utility library handling the low-level HTTP request/response plumbing.
- Jinja2 — the templating engine Flask uses to render HTML.
Because Flask stays out of your way, it's a common choice for small APIs, microservices, prototypes, and any project where a team wants full control over structure rather than inheriting one.
Flask vs Django: two philosophies
Flask and Django are the two most common Python web frameworks, and they sit at opposite ends of the same spectrum:
| Flask | Django | |
|---|---|---|
| Philosophy | Micro-framework — bring your own pieces | Batteries-included — ORM, admin, auth ship built in |
| ORM | Not included (commonly paired with SQLAlchemy) | Django ORM included |
| Admin panel | Not included | Auto-generated admin site included |
| Project layout | Unopinionated — you decide | A generated project/app structure |
| Best for | Small APIs, microservices, projects that want full control | Larger, more conventional applications that want structure out of the box |
| Learning curve | Gentle to start, more decisions as the app grows | More to learn up front, fewer decisions later |
Neither is objectively better — Flask trades built-in structure for flexibility, Django trades some flexibility for a productive, consistent structure. Plenty of real production systems are built on each.
Installing Flask
Install Flask with pip, ideally inside a virtual environment so its dependencies don't leak into (or clash with) other projects:
python3 -m venv venv
source venv/bin/activate # on Windows: venv\Scripts\activate
pip install flask
Confirm the install:
python3 -c "import flask; print(flask.__version__)"
# 3.0.3
Your first Flask app
A complete, runnable Flask application fits in a few lines:
# app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "Hello, World!"
if __name__ == "__main__":
app.run(debug=True)
Flask(__name__) creates the application object — passing __name__ lets Flask figure out the root path of your app so it can find things like the templates/ and static/ folders relative to it. The @app.route("/") decorator registers home() as the function that runs whenever a request comes in for /. Whatever the function returns becomes the HTTP response body — here, a plain string.
Running the development server
There are two common ways to start the app during development.
Directly with Python (using the app.run() call at the bottom of the file):
python3 app.py
With the flask CLI, which doesn't require an if __name__ == "__main__" block at all:
export FLASK_APP=app.py # on Windows: set FLASK_APP=app.py
export FLASK_DEBUG=1
flask run
Either way, visiting http://127.0.0.1:5000 in a browser shows Hello, World!. debug=True (or FLASK_DEBUG=1) turns on the auto-reloader (the server restarts itself whenever you save a code change) and an interactive in-browser debugger for unhandled exceptions — both are enormously useful while developing and both must be off in production.
Common mistakes
- Leaving
debug=Trueactive in a deployed app — the interactive debugger it enables can execute arbitrary Python code from a browser, which is a severe security hole outside of local development. - Running
python3 app.py/flask runin production — the built-in development server is single-threaded and explicitly documented as unsuitable for production traffic; real deployments sit behind a production WSGI server like Gunicorn or uWSGI. - Installing Flask globally instead of inside a virtual environment, leading to version conflicts between unrelated projects on the same machine.
Interview questions
Q: What does "WSGI" mean, and why does it matter for Flask? WSGI (Web Server Gateway Interface) is a standard Python spec describing how a web server talks to a Python web application — a common interface so any WSGI-compliant server (Gunicorn, uWSGI, Waitress) can run any WSGI-compliant framework (Flask, Django). Flask is built directly on Werkzeug's WSGI implementation, which is why it can run behind any standard Python application server rather than needing a custom protocol of its own.
Q: If Flask calls itself a "microframework," how do real, large production apps get built with it? "Micro" describes the small, unopinionated core — not a limit on what you can build. Larger Flask apps add exactly the structure they need through extensions and conventions (Flask-SQLAlchemy for an ORM, Flask-Login for auth, blueprints to split the app into modules, an application factory for configuration) rather than inheriting a one-size-fits-all structure the way Django provides out of the box.