Skip to main content

Architecture Overview

This section contains architecture diagrams and documentation for Flask.

Available Diagrams

Flask Framework Ecosystem Context

This system context diagram illustrates the Flask Framework Ecosystem Context ecosystem and its interactions with external actors and systems.

The Flask Framework sits at the center, acting as the core library that developers use to build web applications.

Key Interactions:

  • Developer: Interacts with the framework by writing application code and using the Click-powered CLI for tasks like running the development server or managing database migrations.
  • Web Browser / Client: Sends HTTP requests to the WSGI Server, which then communicates with the Flask application via the standard WSGI interface.
  • WSGI Server: Acts as the bridge between the network and the Flask application. In production, this is typically a server like Gunicorn or uWSGI; in development, Flask uses the built-in Werkzeug server.
  • Werkzeug: Provides the underlying WSGI utilities, including routing, request/response handling, and the development server.
  • Jinja2: The default template engine used by Flask to render dynamic HTML content.
  • ItsDangerous: Used by Flask to cryptographically sign session cookies and other data to ensure security.
  • Flask Extensions: A vast ecosystem of third-party libraries (e.g., Flask-SQLAlchemy, Flask-Login) that integrate directly with the Flask application object to provide additional features.
  • Environment Variables / .env: Configuration is often loaded from the system environment or .env files, facilitated by Python-Dotenv.
  • Blinker: Provides the signaling system that allows decoupled components to respond to events within the application lifecycle.

Key Architectural Findings:

  • Flask is a WSGI-compliant web framework that relies on Werkzeug for core HTTP and routing functionality.
  • Jinja2 is integrated as the primary template engine for rendering dynamic content.
  • The framework includes a built-in CLI powered by Click for development and administrative tasks.
  • Security features like session signing are handled by the ItsDangerous library.
  • Flask supports a modular extension system, allowing third-party libraries to hook into the application lifecycle.
  • Configuration can be dynamically loaded from environment variables and .env files using python-dotenv.
  • Internal event handling and decoupling are achieved through the Blinker signaling library.

Flask Internal Module Architecture

This component architecture diagram illustrates the internal structure of the Flask web framework.

The architecture is centered around the Flask class, which serves as the primary application object. Both Flask and Blueprint inherit from a common Scaffold base class, which provides the core API for registering routes, error handlers, and request lifecycle hooks.

Key subsystems include:

  • Core Application: Managed by Flask, which coordinates between various internal services.
  • Context Management: Handled by AppContext, which encapsulates the state for both the application and individual requests (including the request, session, and g globals).
  • Modularization: Provided by Blueprint, allowing developers to define routes and handlers independently of the main application and register them later.
  • Services: Including Config for configuration management, SessionInterface for session persistence, and Environment for Jinja2 integration.
  • CLI: The command-line interface is powered by FlaskGroup, which uses ScriptInfo to discover and load the application instance.

The diagram highlights the "recording" pattern used by Blueprints, where operations are deferred until registration with the main Flask object. It also shows how the AppContext acts as a bridge between the application and the active request state.

Key Architectural Findings:

  • Flask and Blueprint share a common base class, Scaffold, which handles the registration of routes and hooks.
  • As of recent versions, RequestContext and AppContext have merged into a single AppContext class that manages the full lifecycle of a request or CLI command.
  • Blueprints use a deferred execution pattern, recording setup operations that are only applied when the blueprint is registered to a Flask application.
  • The session management is abstracted through the SessionInterface, allowing for pluggable session backends beyond the default secure cookie implementation.
  • The CLI subsystem (FlaskGroup) is decoupled from the main application object but uses ScriptInfo to dynamically load the app for command execution.

Request-Response Lifecycle Flow

This sequence diagram illustrates the lifecycle of a request in Flask, from the moment it is received by the WSGI server to the point where a response is returned.

The process begins with the WSGI server calling the Flask application's __call__ method, which delegates to wsgi_app. A new AppContext (which in modern Flask versions like this one, has merged with the former RequestContext) is created to manage the request's state.

During the context's push phase, the MapAdapter (from Werkzeug) is used to match the incoming request URL against the application's routing rules. Once matched, the request is dispatched through full_dispatch_request, which handles preprocessing (like before_request hooks), the actual view function execution, and post-processing (like after_request hooks).

Finally, the return value from the view is converted into a proper Response object, which is then called as a WSGI application to send the data back to the server. The context is then popped, triggering teardown functions.

Key Architectural Findings:

  • Flask 3.2+ has merged RequestContext into AppContext, simplifying the context stack.
  • The request-response lifecycle is managed primarily within the wsgi_app method of the Flask class.
  • Routing is performed during the context push phase via AppContext.match_request using Werkzeug's MapAdapter.
  • The full_dispatch_request method orchestrates preprocessing, dispatching to view functions, and finalizing the response.
  • Context management now uses Python's contextvars (via _cv_app) instead of the legacy _request_ctx_stack.

Flask AppContext and RequestContext Lifecycle

This state diagram illustrates the lifecycle of the AppContext (which now encompasses the functionality previously held by RequestContext in Flask 3.2+).

The lifecycle begins with the creation of an AppContext instance, either via app.app_context() for a pure application context or app.request_context(environ) for a request-aware context.

When push() is called, the context is bound to the current execution thread/task using a contextvars.ContextVar named _cv_app. If it's a request context, it automatically handles session opening and request matching (routing).

The Active state represents the period where the context is available via flask.globals proxies like current_app, g, request, and session. Flask supports nested pushes of the same context, tracked by a _push_count.

The Popping phase occurs when pop() is called. Cleanup only happens when the _push_count reaches zero. This cleanup involves calling teardown functions for both the request (if applicable) and the application context, closing the request, and finally resetting the global state.

Key signals are emitted throughout the lifecycle, allowing extensions to hook into these transitions.

Key Architectural Findings:

  • In Flask 3.2+, RequestContext has been merged into AppContext; they share the same underlying class and lifecycle logic.
  • The context lifecycle is managed by push() and pop() methods, which use contextvars to maintain state across async tasks and threads.
  • A _push_count attribute allows the same context instance to be pushed multiple times, with cleanup only occurring on the final pop.
  • Request-specific initialization (session opening, routing) is performed during the push() operation if request data is present.
  • Teardown functions (teardown_request and teardown_appcontext) are executed in reverse order of registration during the final pop().
  • The flask.globals proxies (current_app, g, request, session) are implemented as LocalProxy objects pointing to the active AppContext in the _cv_app ContextVar.