Skip to main content

Environment Variable Integration

Flask provides two primary ways to integrate environment variables into your application configuration: loading a configuration file via a path stored in an environment variable, or loading variables directly into the configuration object based on a prefix.

Loading from a Configuration File Path​

When you need to keep sensitive information or environment-specific settings out of your source code, you can point Flask to a configuration file using an environment variable with from_envvar.

import flask

app = flask.Flask(__name__)

# Load configuration from a file path specified in the 'APP_SETTINGS' env var
app.config.from_envvar("APP_SETTINGS")

If the environment variable APP_SETTINGS is set to /var/www/app/config.py, Flask will execute that file and load its uppercase variables.

Handling Missing Variables​

By default, from_envvar raises a RuntimeError if the environment variable is not set. You can suppress this by passing silent=True.

# Returns False instead of raising RuntimeError if 'OPTIONAL_SETTINGS' is missing
app.config.from_envvar("OPTIONAL_SETTINGS", silent=True)

Loading Prefixed Variables Directly​

You can load environment variables directly into the Config object using from_prefixed_env. By default, it looks for variables starting with FLASK_.

import flask
import os

# Set environment variables (usually done in your shell)
# export FLASK_SECRET_KEY="local-dev-key"
# export FLASK_DEBUG="true"

app = flask.Flask(__name__)
app.config.from_prefixed_env()

print(app.config["SECRET_KEY"]) # "local-dev-key"
print(app.config["DEBUG"]) # True (automatically parsed)

Automatic Type Conversion​

The from_prefixed_env method uses json.loads by default to attempt to parse values. This allows you to pass booleans, integers, lists, and dictionaries directly from the environment.

# export FLASK_PORT="5000"        -> app.config["PORT"] == 5000
# export FLASK_ENABLED="true" -> app.config["ENABLED"] is True
# export FLASK_TAGS='["web", "v1"]' -> app.config["TAGS"] == ["web", "v1"]

If a value cannot be parsed as JSON, it remains a string.

Handling Nested Configuration​

Flask supports populating nested dictionaries in your configuration by using a double underscore (__) as a separator in the environment variable name.

# export FLASK_DATABASE__HOST="localhost"
# export FLASK_DATABASE__PORT="5432"

app = flask.Flask(__name__)
app.config.from_prefixed_env()

# Resulting config structure:
# app.config["DATABASE"] == {"HOST": "localhost", "PORT": 5432}

If an intermediate key (like DATABASE in the example above) does not exist, Flask initializes it as an empty dictionary.

Customizing the Prefix and Parsing​

You can change the prefix Flask looks for or provide a custom loading function for values.

import json
import flask

app = flask.Flask(__name__)

# Load variables starting with 'MYAPP_' instead of 'FLASK_'
app.config.from_prefixed_env(prefix="MYAPP")

# Use a custom loader (e.g., to disable JSON parsing and keep everything as strings)
app.config.from_prefixed_env(loads=lambda x: x)

Troubleshooting​

Uppercase Key Requirement​

Flask's Config class only tracks uppercase keys when loading from files or objects. While from_prefixed_env will load keys regardless of case (stripping the prefix), it is a standard convention in Flask to use uppercase for all configuration keys.

Windows Environment Variables​

On Windows, environment variable keys are always uppercase. This can impact nested dictionary loading if your application logic expects specific casing for sub-keys. For example, FLASK_EXIST__ok will be read as FLASK_EXIST__OK on Windows, resulting in app.config["EXIST"]["OK"] instead of app.config["EXIST"]["ok"].

JSON Parsing Failures​

If from_prefixed_env encounters a value that looks like JSON but is malformed, it catches the exception and treats the value as a raw string.

# export FLASK_DATA='{"key": "missing-quote}' 
app.config.from_prefixed_env()
# app.config["DATA"] will be the literal string '{"key": "missing-quote}'