Configuration & Environments
Flask configuration is the set of key-value settings — like SECRET_KEY , DEBUG , and database URLs — that control how your app behaves in development versus production.
Learn Configuration & Environments in our free Flask course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Flask course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll load settings from config classes, set them directly from a mapping, pull secrets from environment variables, and split your app cleanly into Dev and Prod environments.
Every Flask app exposes app.config , a dictionary-like object holding all of your settings. You can write to it key-by-key, but the cleanest pattern for real apps is to group settings into a config class and load them all at once with app.config.from_object(...) .
A base Config class holds shared defaults, and environment-specific classes like DevConfig and ProdConfig inherit from it and override only what changes. Crucially, from_object copies only UPPERCASE attributes into the config — lowercase names are ignored, which keeps internal helpers out of your settings.
The example below loads DevConfig . Notice that SECRET_KEY is inherited from the base Config class, and .get() safely returns a fallback for keys that were never set.
Because DevConfig overrides only DEBUG , the SECRET_KEY it reports comes straight from the parent Config — class inheritance and config inheritance line up perfectly.
When you want to set several keys without defining a class, app.config.from_mapping(...) takes keyword arguments (or a dictionary) and writes them all into the config in one call. It's perfect for small apps, tests, and supplying defaults before layering other sources on top.
Remember that app.config is fundamentally a dict, so you can also assign a single key directly with app.config["KEY"] = value . The example below sets three keys at once, then overwrites one of them.
from_mapping is ideal for defaults and tests; mixing it with direct app.config["KEY"] = ... assignment gives you fine-grained control whenever you need it.
Secrets and deployment-specific values — API keys, database passwords, the real SECRET_KEY — should never live in your source code. The standard practice is to keep them in environment variables and read them at startup, so the same code runs everywhere while each machine supplies its own secrets.
app.config.from_prefixed_env("FLASK") scans the environment for every variable starting with FLASK_ , strips that prefix, and stores the rest as config keys. So FLASK_API_KEY becomes API_KEY . Flask also tries to JSON-parse each value, so the string "25" becomes the integer 25 , while plain text stays a string.
Notice API_KEY stays the string abc123 , while PAGE_SIZE is the integer 25 — Flask JSON-parsed the numeric value automatically, so you don't have to convert it yourself.
Rule of thumb: group shared settings in a base Config class, override per environment in DevConfig / ProdConfig , and pull secrets from the environment.
Complete the code below. Replace each ___ so it loads DevConfig and reads two settings out of app.config .
Hint: the method that copies a class into config is from_object , and config keys are strings like "DEBUG" and "SECRET_KEY" .
❌ Lowercase config names are silently ignored
from_object only copies UPPERCASE attributes. If you write debug = True or secret_key = "x" in your class, Flask skips them entirely and your settings never take effect. Always use DEBUG , SECRET_KEY , and other ALL-CAPS names.
❌ Missing SECRET_KEY breaks sessions and flash
Using session or flash() without a SECRET_KEY raises RuntimeError: The session is unavailable because no secret key was set . Set a real, random key — loaded from the environment in production — before using either feature.
Wire up two config classes and choose between them at startup based on an environment variable.
Switch APP_ENV to anything other than production (or remove it) and the app falls back to DevConfig with DEBUG on — one variable flips your entire environment.
Lesson complete — your app is ready for any environment!
You can load settings from config classes with from_object , set keys with from_mapping , pull secrets from the environment with from_prefixed_env , and split your app into Dev and Prod with a single SECRET_KEY and the right DEBUG value.
🚀 Up next: Application & Request Context — understand how Flask makes app , g , and request available at the right time.
Practice quiz
What is app.config?
- A read-only constant
- A dictionary-like object storing every setting
- A route decorator
- A logging handler
Answer: A dictionary-like object storing every setting. app.config is a dict-like object holding all of your settings.
What does from_object copy into the config?
- Only UPPERCASE attributes of a class or module
- Every attribute including lowercase
- Only environment variables
- Only methods
Answer: Only UPPERCASE attributes of a class or module. from_object copies only UPPERCASE attributes, ignoring lowercase names.
Which method sets several keys directly from keyword arguments?
- from_object
- from_envvar
- from_mapping
- from_pyfile
Answer: from_mapping. from_mapping(KEY=value, ...) sets several keys at once.
What does from_prefixed_env('FLASK') do?
- Loads a Python file
- Reads a JSON config file
- Copies a config class
- Pulls FLASK_* env vars into config with the prefix stripped
Answer: Pulls FLASK_* env vars into config with the prefix stripped. from_prefixed_env('FLASK') loads FLASK_* vars, stripping the prefix.
What is SECRET_KEY used for?
- Naming the app
- Cryptographically signing session cookies and flash messages
- Enabling DEBUG
- Choosing the database
Answer: Cryptographically signing session cookies and flash messages. SECRET_KEY signs session cookies and flash messages so they can't be tampered with.
Why should DEBUG be False in production?
- It disables routing
- It slows the app down
- True enables an interactive debugger that runs arbitrary code
- True disables logging
Answer: True enables an interactive debugger that runs arbitrary code. DEBUG=True exposes the Werkzeug debugger, a critical security hole in production.
What happens to a lowercase attribute like debug=True in a config class?
- It is silently ignored by from_object
- It overrides DEBUG
- It raises an error
- It becomes 'DEBUG'
Answer: It is silently ignored by from_object. from_object only copies UPPERCASE names, so lowercase ones are ignored.
How do you read a config value with a fallback default?
- app.config.read('KEY')
- app.config.default('KEY')
- app.config.fetch('KEY', d)
- app.config.get('KEY', default)
Answer: app.config.get('KEY', default). app.config.get('KEY', default) safely returns a fallback.
What error does using session without SECRET_KEY raise?
- RuntimeError: the session is unavailable because no secret key was set
- 404 Not Found
- KeyError: SESSION
- ValueError: bad cookie
Answer: RuntimeError: the session is unavailable because no secret key was set. Without SECRET_KEY, session and flash raise a RuntimeError.
Does from_prefixed_env try to JSON-parse values?
- No, everything stays a string
- Only booleans
- Yes, so '25' becomes the integer 25
- Only if you pass parse=True
Answer: Yes, so '25' becomes the integer 25. Flask JSON-parses each value, so '25' becomes int 25 while plain text stays a string.