Skip to main content

The Application Context

When you try to access current_app.config or use url_for() in a script or a background task, you might encounter a RuntimeError: Working outside of application context. This happens because Flask uses an Application Context to keep track of application-level data during a request, CLI command, or other execution cycle.

The application context ensures that the current_app and g proxies point to the correct application instance without requiring you to pass the app object through every function in your codebase.

The current_app Proxy​

The current_app object is a FlaskProxy that points to the application handling the current activity. Instead of importing your app instance directly—which can lead to circular imports in larger projects—you use current_app to access configuration, loggers, and other application-level attributes.

from flask import current_app

def get_storage_path():
# Accesses the config of the currently active Flask app
return current_app.config["STORAGE_PATH"]

Internally, current_app is defined in flask.globals as a LocalProxy that looks up the app attribute on the active AppContext.

Storing Data with the g Object​

The g object (short for "globals") is a namespace for storing data during an application context. It is commonly used to manage resources like database connections so they can be reused across a single request or CLI command.

In examples/tutorial/flaskr/db.py, Flask uses g to ensure a database connection is only created once per request:

from flask import g, current_app
import sqlite3

def get_db():
if "db" not in g:
g.db = sqlite3.connect(
current_app.config["DATABASE"],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
return g.db

The g object is an instance of _AppCtxGlobals and is attached to the AppContext. When the context is popped, the data in g is cleared.

Lifecycle of the Context​

Flask automatically manages the application context during the lifecycle of an HTTP request or a CLI command.

  1. Push: At the start of a request, Flask creates an AppContext and calls push(). This sets the internal contextvars token so that current_app and g become available.
  2. Execution: Your view functions or CLI commands run.
  3. Pop: When the request ends, Flask calls pop(). This triggers teardown functions and removes the context from the stack.

Manual Context Management​

If you need to access the application context outside of a request—for example, in a unit test or a standalone script—you must push it manually using the app.app_context() context manager.

from myapp import create_app
from flask import current_app

app = create_app()

with app.app_context():
# current_app is now available
print(current_app.name)

The AppContext class in src/flask/ctx.py implements the __enter__ and __exit__ methods to handle this:

def __enter__(self) -> te.Self:
self.push()
return self

def __exit__(self, exc_type, exc_value, tb) -> None:
self.pop(exc_value)

Teardown and Cleanup​

When an application context is popped, Flask executes functions registered with @app.teardown_appcontext. These functions run even if an unhandled exception occurred during the request, making them ideal for closing database connections or releasing resources.

You register these functions using the teardown_appcontext decorator:

def close_db(e=None):
db = g.pop("db", None)
if db is not None:
db.close()

app.teardown_appcontext(close_db)

Internally, AppContext.pop calls self.app.do_teardown_appcontext(self, exc), which iterates through all registered teardown functions.

Context Merging in Flask 3.2+​

Starting with Flask 3.2, the RequestContext has been merged into AppContext. Previously, Flask maintained two separate stacks. Now, a single AppContext instance handles both application-level data and request-level data (if a request is active).

The AppContext class now includes properties for request and session:

@property
def request(self) -> Request:
if self._request is None:
raise RuntimeError("There is no request in this context.")
return self._request

If you attempt to access request or session when the AppContext was pushed without request data (e.g., in a CLI command), Flask raises a RuntimeError.

URL Generation Pitfalls​

A common issue occurs when calling url_for() outside of a request context (e.g., in a background task to generate a link for an email). Because there is no incoming request to determine the host and port, url_for will fail unless the SERVER_NAME configuration variable is set.

# In your config
SERVER_NAME = "example.com"

# In your task
with app.app_context():
url = url_for("index", _external=True)

If SERVER_NAME is provided, the AppContext uses it to initialize a url_adapter even when no request is present, allowing for external URL generation.