100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Python

Flask Configuration Management

Layering config classes, environment variables, and .env files to manage Flask settings and secrets safely across development, testing, and production.

Advanced FlaskIntermediate10 min readJul 10, 2026
Analogies

Configuration Sources in Flask

Flask's app.config object is a dictionary subclass that can be populated from multiple sources: hardcoded defaults via app.config.from_object(SomeClass), environment variables via app.config.from_prefixed_env(), a Python file via from_pyfile(), or a plain dict via from_mapping(). Layering these lets a team keep sensible defaults in code while overriding secrets like SECRET_KEY or DATABASE_URL through environment variables that never get committed to source control.

🏏

Cricket analogy: A team sets a default batting order in the pre-season plan but adjusts it on matchday based on pitch conditions and the toss, just as Flask loads default config from a class but can override values from environment variables.

Environment-Based Config Classes

A common pattern defines a base Config class with shared settings, then subclasses for DevelopmentConfig, TestingConfig, and ProductionConfig that override specific values like DEBUG, TESTING, or SQLALCHEMY_DATABASE_URI. Sensitive values like SECRET_KEY and database credentials are read from os.environ inside the base class so they're never hardcoded, and the appropriate subclass is selected at create_app() time based on an environment variable like FLASK_ENV or a deployment-specific entrypoint.

🏏

Cricket analogy: A cricket board has a base rulebook but separate addenda for T20, ODI, and Test formats overriding specific rules like over limits, just as DevelopmentConfig, TestingConfig, and ProductionConfig override specific base Config values.

python
import os

class Config:
    SECRET_KEY = os.environ.get("SECRET_KEY", "dev-key-change-me")
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class DevelopmentConfig(Config):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = "sqlite:///dev.db"

class TestingConfig(Config):
    TESTING = True
    SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
    WTF_CSRF_ENABLED = False

class ProductionConfig(Config):
    DEBUG = False
    SQLALCHEMY_DATABASE_URI = os.environ["DATABASE_URL"]

Secrets and the .env File

Local development commonly uses a .env file loaded via python-dotenv to populate os.environ before the config classes read from it, keeping SECRET_KEY, database passwords, and API keys out of version control. In production, these same variable names are set directly in the deployment environment (Docker Compose env_file, Kubernetes secrets, or a platform's environment variable settings) so the identical config-loading code works unchanged across environments.

🏏

Cricket analogy: A team keeps its confidential match strategy in a sealed dressing-room folder that never leaves the venue, just as a .env file with secrets stays out of the public git repository via .gitignore.

A ProductionConfig that raises a KeyError on os.environ['DATABASE_URL'] rather than silently defaulting is intentional: it forces the deployment to explicitly set required secrets rather than accidentally running production against a fallback SQLite file.

Never commit a .env file containing real secrets to version control — add it to .gitignore and commit only a .env.example template with placeholder values, since leaked SECRET_KEY values allow attackers to forge session cookies.

  • Flask's app.config supports layered loading: from_object() for code defaults, from_pyfile() for files, from_prefixed_env() for environment variables.
  • A base Config class holds shared settings; DevelopmentConfig, TestingConfig, and ProductionConfig override environment-specific values.
  • Secrets like SECRET_KEY and DATABASE_URL should be read from os.environ, never hardcoded in source.
  • python-dotenv loads a local .env file into os.environ for development convenience.
  • .env files with real secrets must be excluded from version control via .gitignore.
  • ProductionConfig should fail loudly (KeyError) on missing required secrets rather than silently falling back to insecure defaults.
  • The same config-loading code should work unchanged across dev, test, and prod by relying on environment variables.

Practice what you learned

Was this page helpful?

Topics covered

#Python#FlaskStudyNotes#WebDevelopment#FlaskConfigurationManagement#Flask#Configuration#Management#Sources#StudyNotes#SkillVeris