Skip to main content

Application Configuration Management

When you build a Flask application, you often need to manage different settings for development, testing, and production. The App class provides a config attribute (an instance of the Config class) that serves as a central dictionary for these settings, with specialized methods for loading values from files, objects, and environment variables.

Initializing Configuration in an App Factory

The most common way to manage configuration is within an application factory. This allows you to set defaults and then override them based on the environment.

import os
from flask import Flask

def create_app(test_config=None):
# instance_relative_config=True makes relative paths in config loading
# relative to the instance folder instead of the app root.
app = Flask(__name__, instance_relative_config=True)

# 1. Set default configuration
app.config.from_mapping(
SECRET_KEY="dev",
DATABASE=os.path.join(app.instance_path, "flaskr.sqlite"),
)

if test_config is None:
# 2. Load the instance config, if it exists, when not testing
# silent=True prevents an error if the file is missing
app.config.from_pyfile("config.py", silent=True)
else:
# 3. Load the test config if passed in
app.config.from_mapping(test_config)

return app

Loading Strategies

Flask provides several methods on the Config class to populate settings. Note that for most methods, only uppercase keys are loaded.

Programmatic Defaults

Use from_mapping to set multiple values at once using a dictionary or keyword arguments.

app.config.from_mapping(
DEBUG=True,
PORT=5000
)

Python Configuration Files

Use from_pyfile to load values from a .py or .cfg file. Flask executes the file and pulls out all top-level variables defined in uppercase.

# Loads from <root_path>/settings.cfg
app.config.from_pyfile("settings.cfg")

JSON and TOML Files

Use from_file to load from other formats. You must provide a loader function (like json.load).

import json
import tomllib

# Load from a JSON file
app.config.from_file("config.json", load=json.load)

# Load from a TOML file (requires binary mode)
app.config.from_file("config.toml", load=tomllib.load, text=False)

Environment Variables

The from_prefixed_env method is the modern way to load configuration from the environment. By default, it looks for variables starting with FLASK_.

# If export FLASK_SECRET_KEY="local-dev" is set in the shell:
app.config.from_prefixed_env()
assert app.config["SECRET_KEY"] == "local-dev"

Values loaded via from_prefixed_env are automatically parsed as JSON. This allows you to pass complex types like lists or booleans:

# export FLASK_DEBUG=true  -> app.config["DEBUG"] becomes True (bool)
# export FLASK_PORT=8080 -> app.config["PORT"] becomes 8080 (int)
app.config.from_prefixed_env()

You can also use double underscores (__) in environment variables to create nested dictionaries:

# export FLASK_DATABASE__HOST="localhost"
app.config.from_prefixed_env()
# Result: app.config["DATABASE"] == {"HOST": "localhost"}

Using Instance Folders

Flask supports an "instance folder" for deployment-specific files that should not be committed to version control (like database files or secrets).

When you initialize App(instance_relative_config=True), the config.from_pyfile() and config.from_file() methods will look for files relative to app.instance_path.

# The instance path is usually at /path/to/app/instance
app = Flask(__name__, instance_relative_config=True)

# This looks for /path/to/app/instance/config.py
app.config.from_pyfile("config.py")

Accessing Configuration

You can access configuration values directly via the app.config dictionary. Additionally, the App class defines several ConfigAttribute descriptors that proxy directly to the config dictionary.

# These two are equivalent:
app.config["DEBUG"] = True
app.debug = True

# Common ConfigAttributes available on the App class:
print(app.secret_key) # Proxies to app.config["SECRET_KEY"]
print(app.testing) # Proxies to app.config["TESTING"]
print(app.permanent_session_lifetime) # Proxies to app.config["PERMANENT_SESSION_LIFETIME"]

Troubleshooting and Constraints

Uppercase Key Requirement

When loading from objects, modules, or Python files, Flask ignores any variable that is not fully uppercase.

# In config.py
DEBUG = True # Loaded
database = "db" # IGNORED

Dictionary vs. Object Loading

from_object works with modules or classes by looking at attributes. It does not work with plain dictionaries. Use from_mapping for dictionaries.

class DefaultConfig:
DEBUG = True

app.config.from_object(DefaultConfig) # Works
app.config.from_object({"DEBUG": True}) # Fails (dicts don't have uppercase attributes)

Environment Variable Parsing

If from_prefixed_env fails to parse a value as JSON, it will fall back to treating the value as a raw string. If you want a value to be a string but it looks like a JSON type (like the string "true"), ensure your environment variable is quoted correctly for your shell.