[{"data":1,"prerenderedAt":2234},["ShallowReactive",2],{"\u002Freference\u002Fflask-config-environments-dev-vs-staging-vs-production":3},{"id":4,"title":5,"body":6,"description":2224,"extension":2225,"meta":2226,"navigation":69,"path":2230,"seo":2231,"stem":2232,"__hash__":2233},"content\u002Freference\u002Fflask-config-environments-dev-vs-staging-vs-production.md","Flask Config Environments: Dev vs Staging vs Production",{"type":7,"value":8,"toc":2213},"minimark",[9,13,17,22,30,349,359,363,366,370,1741,1745,1814,1818,1821,1854,1857,1869,1872,1941,1944,1960,1963,1997,2000,2035,2042,2046,2107,2111,2131,2135,2143,2151,2159,2167,2178,2191,2202,2206,2209],[10,11,5],"h1",{"id":12},"flask-config-environments-dev-vs-staging-vs-production",[14,15,16],"p",{},"If you're trying to separate Flask development, staging, and production settings, this guide shows you how to structure environment-specific config step-by-step. The goal is to prevent unsafe defaults, avoid mixing secrets and databases, and make deployments predictable.",[18,19,21],"h2",{"id":20},"quick-fix-quick-setup","Quick Fix \u002F Quick Setup",[14,23,24,25,29],{},"Create a central config module, load it through an app factory, and select the active environment with ",[26,27,28],"code",{},"FLASK_CONFIG",".",[31,32,37],"pre",{"className":33,"code":34,"language":35,"meta":36,"style":36},"language-bash shiki shiki-themes github-light github-dark","mkdir -p \u002Fvar\u002Fwww\u002Fmyapp\ncd \u002Fvar\u002Fwww\u002Fmyapp\n\ncat > config.py \u003C\u003C'EOF'\nimport os\n\nclass BaseConfig:\n    SECRET_KEY = os.environ.get('SECRET_KEY', 'change-me')\n    SQLALCHEMY_TRACK_MODIFICATIONS = False\n\nclass DevelopmentConfig(BaseConfig):\n    DEBUG = True\n    TESTING = False\n    ENV_NAME = 'development'\n    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL', 'sqlite:\u002F\u002F\u002Fdev.db')\n\nclass StagingConfig(BaseConfig):\n    DEBUG = False\n    TESTING = False\n    ENV_NAME = 'staging'\n    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')\n\nclass ProductionConfig(BaseConfig):\n    DEBUG = False\n    TESTING = False\n    ENV_NAME = 'production'\n    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')\n    SESSION_COOKIE_SECURE = True\n    REMEMBER_COOKIE_SECURE = True\n    PREFERRED_URL_SCHEME = 'https'\nEOF\n\ncat > wsgi.py \u003C\u003C'EOF'\nimport os\nfrom myapp import create_app\n\napp = create_app(os.environ.get('FLASK_CONFIG', 'production'))\nEOF\n\nexport FLASK_CONFIG=development\nexport SECRET_KEY='dev-secret'\nexport DATABASE_URL='sqlite:\u002F\u002F\u002Fdev.db'\npython -c \"from wsgi import app; print(app.config['ENV_NAME'], app.config['DEBUG'])\"\n","bash","",[26,38,39,56,64,71,90,96,101,107,113,119,124,130,136,142,148,154,159,165,171,176,182,188,193,199,204,209,215,220,226,232,238,244,249,263,268,274,279,285,290,295,311,324,337],{"__ignoreMap":36},[40,41,44,48,52],"span",{"class":42,"line":43},"line",1,[40,45,47],{"class":46},"sScJk","mkdir",[40,49,51],{"class":50},"sj4cs"," -p",[40,53,55],{"class":54},"sZZnC"," \u002Fvar\u002Fwww\u002Fmyapp\n",[40,57,59,62],{"class":42,"line":58},2,[40,60,61],{"class":50},"cd",[40,63,55],{"class":54},[40,65,67],{"class":42,"line":66},3,[40,68,70],{"emptyLinePlaceholder":69},true,"\n",[40,72,74,77,81,84,87],{"class":42,"line":73},4,[40,75,76],{"class":46},"cat",[40,78,80],{"class":79},"szBVR"," >",[40,82,83],{"class":54}," config.py",[40,85,86],{"class":79}," \u003C\u003C",[40,88,89],{"class":54},"'EOF'\n",[40,91,93],{"class":42,"line":92},5,[40,94,95],{"class":54},"import os\n",[40,97,99],{"class":42,"line":98},6,[40,100,70],{"emptyLinePlaceholder":69},[40,102,104],{"class":42,"line":103},7,[40,105,106],{"class":54},"class BaseConfig:\n",[40,108,110],{"class":42,"line":109},8,[40,111,112],{"class":54},"    SECRET_KEY = os.environ.get('SECRET_KEY', 'change-me')\n",[40,114,116],{"class":42,"line":115},9,[40,117,118],{"class":54},"    SQLALCHEMY_TRACK_MODIFICATIONS = False\n",[40,120,122],{"class":42,"line":121},10,[40,123,70],{"emptyLinePlaceholder":69},[40,125,127],{"class":42,"line":126},11,[40,128,129],{"class":54},"class DevelopmentConfig(BaseConfig):\n",[40,131,133],{"class":42,"line":132},12,[40,134,135],{"class":54},"    DEBUG = True\n",[40,137,139],{"class":42,"line":138},13,[40,140,141],{"class":54},"    TESTING = False\n",[40,143,145],{"class":42,"line":144},14,[40,146,147],{"class":54},"    ENV_NAME = 'development'\n",[40,149,151],{"class":42,"line":150},15,[40,152,153],{"class":54},"    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL', 'sqlite:\u002F\u002F\u002Fdev.db')\n",[40,155,157],{"class":42,"line":156},16,[40,158,70],{"emptyLinePlaceholder":69},[40,160,162],{"class":42,"line":161},17,[40,163,164],{"class":54},"class StagingConfig(BaseConfig):\n",[40,166,168],{"class":42,"line":167},18,[40,169,170],{"class":54},"    DEBUG = False\n",[40,172,174],{"class":42,"line":173},19,[40,175,141],{"class":54},[40,177,179],{"class":42,"line":178},20,[40,180,181],{"class":54},"    ENV_NAME = 'staging'\n",[40,183,185],{"class":42,"line":184},21,[40,186,187],{"class":54},"    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')\n",[40,189,191],{"class":42,"line":190},22,[40,192,70],{"emptyLinePlaceholder":69},[40,194,196],{"class":42,"line":195},23,[40,197,198],{"class":54},"class ProductionConfig(BaseConfig):\n",[40,200,202],{"class":42,"line":201},24,[40,203,170],{"class":54},[40,205,207],{"class":42,"line":206},25,[40,208,141],{"class":54},[40,210,212],{"class":42,"line":211},26,[40,213,214],{"class":54},"    ENV_NAME = 'production'\n",[40,216,218],{"class":42,"line":217},27,[40,219,187],{"class":54},[40,221,223],{"class":42,"line":222},28,[40,224,225],{"class":54},"    SESSION_COOKIE_SECURE = True\n",[40,227,229],{"class":42,"line":228},29,[40,230,231],{"class":54},"    REMEMBER_COOKIE_SECURE = True\n",[40,233,235],{"class":42,"line":234},30,[40,236,237],{"class":54},"    PREFERRED_URL_SCHEME = 'https'\n",[40,239,241],{"class":42,"line":240},31,[40,242,243],{"class":54},"EOF\n",[40,245,247],{"class":42,"line":246},32,[40,248,70],{"emptyLinePlaceholder":69},[40,250,252,254,256,259,261],{"class":42,"line":251},33,[40,253,76],{"class":46},[40,255,80],{"class":79},[40,257,258],{"class":54}," wsgi.py",[40,260,86],{"class":79},[40,262,89],{"class":54},[40,264,266],{"class":42,"line":265},34,[40,267,95],{"class":54},[40,269,271],{"class":42,"line":270},35,[40,272,273],{"class":54},"from myapp import create_app\n",[40,275,277],{"class":42,"line":276},36,[40,278,70],{"emptyLinePlaceholder":69},[40,280,282],{"class":42,"line":281},37,[40,283,284],{"class":54},"app = create_app(os.environ.get('FLASK_CONFIG', 'production'))\n",[40,286,288],{"class":42,"line":287},38,[40,289,243],{"class":54},[40,291,293],{"class":42,"line":292},39,[40,294,70],{"emptyLinePlaceholder":69},[40,296,298,301,305,308],{"class":42,"line":297},40,[40,299,300],{"class":79},"export",[40,302,304],{"class":303},"sVt8B"," FLASK_CONFIG",[40,306,307],{"class":79},"=",[40,309,310],{"class":303},"development\n",[40,312,314,316,319,321],{"class":42,"line":313},41,[40,315,300],{"class":79},[40,317,318],{"class":303}," SECRET_KEY",[40,320,307],{"class":79},[40,322,323],{"class":54},"'dev-secret'\n",[40,325,327,329,332,334],{"class":42,"line":326},42,[40,328,300],{"class":79},[40,330,331],{"class":303}," DATABASE_URL",[40,333,307],{"class":79},[40,335,336],{"class":54},"'sqlite:\u002F\u002F\u002Fdev.db'\n",[40,338,340,343,346],{"class":42,"line":339},43,[40,341,342],{"class":46},"python",[40,344,345],{"class":50}," -c",[40,347,348],{"class":54}," \"from wsgi import app; print(app.config['ENV_NAME'], app.config['DEBUG'])\"\n",[14,350,351,352,354,355,358],{},"Use an app factory and load the config from ",[26,353,28],{},". In production, set ",[26,356,357],{},"FLASK_CONFIG=production"," in systemd or your container environment instead of hardcoding values.",[18,360,362],{"id":361},"whats-happening","What’s Happening",[14,364,365],{},"Flask apps often break across environments because one settings file is reused everywhere. Development needs fast iteration and verbose errors, staging should safely mirror production, and production must disable debug and load real secrets. A clean config split prevents using the wrong database, exposing debug mode, or deploying local defaults to live traffic.",[18,367,369],{"id":368},"step-by-step-guide","Step-by-Step Guide",[371,372,373,651,731,992,1055,1122,1214,1282,1430,1574,1596,1625,1640,1736],"ol",{},[374,375,376,380,383,384],"li",{},[377,378,379],"strong",{},"Create a central config module",[381,382],"br",{},"Put shared settings in a base class and override environment-specific settings in separate subclasses.",[31,385,388],{"className":386,"code":387,"language":342,"meta":36,"style":36},"language-python shiki shiki-themes github-light github-dark","# config.py\nimport os\n\nclass BaseConfig:\n    SECRET_KEY = os.environ.get(\"SECRET_KEY\")\n    SQLALCHEMY_TRACK_MODIFICATIONS = False\n\nclass DevelopmentConfig(BaseConfig):\n    DEBUG = True\n    TESTING = False\n    ENV_NAME = \"development\"\n    SQLALCHEMY_DATABASE_URI = os.environ.get(\"DATABASE_URL\", \"sqlite:\u002F\u002F\u002Fdev.db\")\n\nclass StagingConfig(BaseConfig):\n    DEBUG = False\n    TESTING = False\n    ENV_NAME = \"staging\"\n    SQLALCHEMY_DATABASE_URI = os.environ.get(\"DATABASE_URL\")\n\nclass ProductionConfig(BaseConfig):\n    DEBUG = False\n    TESTING = False\n    ENV_NAME = \"production\"\n    SQLALCHEMY_DATABASE_URI = os.environ.get(\"DATABASE_URL\")\n    SESSION_COOKIE_SECURE = True\n    REMEMBER_COOKIE_SECURE = True\n    PREFERRED_URL_SCHEME = \"https\"\n",[26,389,390,396,404,408,419,436,446,450,466,476,485,495,515,519,532,540,548,557,569,573,586,594,602,611,623,632,641],{"__ignoreMap":36},[40,391,392],{"class":42,"line":43},[40,393,395],{"class":394},"sJ8bj","# config.py\n",[40,397,398,401],{"class":42,"line":58},[40,399,400],{"class":79},"import",[40,402,403],{"class":303}," os\n",[40,405,406],{"class":42,"line":66},[40,407,70],{"emptyLinePlaceholder":69},[40,409,410,413,416],{"class":42,"line":73},[40,411,412],{"class":79},"class",[40,414,415],{"class":46}," BaseConfig",[40,417,418],{"class":303},":\n",[40,420,421,424,427,430,433],{"class":42,"line":92},[40,422,423],{"class":50},"    SECRET_KEY",[40,425,426],{"class":79}," =",[40,428,429],{"class":303}," os.environ.get(",[40,431,432],{"class":54},"\"SECRET_KEY\"",[40,434,435],{"class":303},")\n",[40,437,438,441,443],{"class":42,"line":98},[40,439,440],{"class":50},"    SQLALCHEMY_TRACK_MODIFICATIONS",[40,442,426],{"class":79},[40,444,445],{"class":50}," False\n",[40,447,448],{"class":42,"line":103},[40,449,70],{"emptyLinePlaceholder":69},[40,451,452,454,457,460,463],{"class":42,"line":109},[40,453,412],{"class":79},[40,455,456],{"class":46}," DevelopmentConfig",[40,458,459],{"class":303},"(",[40,461,462],{"class":46},"BaseConfig",[40,464,465],{"class":303},"):\n",[40,467,468,471,473],{"class":42,"line":115},[40,469,470],{"class":50},"    DEBUG",[40,472,426],{"class":79},[40,474,475],{"class":50}," True\n",[40,477,478,481,483],{"class":42,"line":121},[40,479,480],{"class":50},"    TESTING",[40,482,426],{"class":79},[40,484,445],{"class":50},[40,486,487,490,492],{"class":42,"line":126},[40,488,489],{"class":50},"    ENV_NAME",[40,491,426],{"class":79},[40,493,494],{"class":54}," \"development\"\n",[40,496,497,500,502,504,507,510,513],{"class":42,"line":132},[40,498,499],{"class":50},"    SQLALCHEMY_DATABASE_URI",[40,501,426],{"class":79},[40,503,429],{"class":303},[40,505,506],{"class":54},"\"DATABASE_URL\"",[40,508,509],{"class":303},", ",[40,511,512],{"class":54},"\"sqlite:\u002F\u002F\u002Fdev.db\"",[40,514,435],{"class":303},[40,516,517],{"class":42,"line":138},[40,518,70],{"emptyLinePlaceholder":69},[40,520,521,523,526,528,530],{"class":42,"line":144},[40,522,412],{"class":79},[40,524,525],{"class":46}," StagingConfig",[40,527,459],{"class":303},[40,529,462],{"class":46},[40,531,465],{"class":303},[40,533,534,536,538],{"class":42,"line":150},[40,535,470],{"class":50},[40,537,426],{"class":79},[40,539,445],{"class":50},[40,541,542,544,546],{"class":42,"line":156},[40,543,480],{"class":50},[40,545,426],{"class":79},[40,547,445],{"class":50},[40,549,550,552,554],{"class":42,"line":161},[40,551,489],{"class":50},[40,553,426],{"class":79},[40,555,556],{"class":54}," \"staging\"\n",[40,558,559,561,563,565,567],{"class":42,"line":167},[40,560,499],{"class":50},[40,562,426],{"class":79},[40,564,429],{"class":303},[40,566,506],{"class":54},[40,568,435],{"class":303},[40,570,571],{"class":42,"line":173},[40,572,70],{"emptyLinePlaceholder":69},[40,574,575,577,580,582,584],{"class":42,"line":178},[40,576,412],{"class":79},[40,578,579],{"class":46}," ProductionConfig",[40,581,459],{"class":303},[40,583,462],{"class":46},[40,585,465],{"class":303},[40,587,588,590,592],{"class":42,"line":184},[40,589,470],{"class":50},[40,591,426],{"class":79},[40,593,445],{"class":50},[40,595,596,598,600],{"class":42,"line":190},[40,597,480],{"class":50},[40,599,426],{"class":79},[40,601,445],{"class":50},[40,603,604,606,608],{"class":42,"line":195},[40,605,489],{"class":50},[40,607,426],{"class":79},[40,609,610],{"class":54}," \"production\"\n",[40,612,613,615,617,619,621],{"class":42,"line":201},[40,614,499],{"class":50},[40,616,426],{"class":79},[40,618,429],{"class":303},[40,620,506],{"class":54},[40,622,435],{"class":303},[40,624,625,628,630],{"class":42,"line":206},[40,626,627],{"class":50},"    SESSION_COOKIE_SECURE",[40,629,426],{"class":79},[40,631,475],{"class":50},[40,633,634,637,639],{"class":42,"line":211},[40,635,636],{"class":50},"    REMEMBER_COOKIE_SECURE",[40,638,426],{"class":79},[40,640,475],{"class":50},[40,642,643,646,648],{"class":42,"line":217},[40,644,645],{"class":50},"    PREFERRED_URL_SCHEME",[40,647,426],{"class":79},[40,649,650],{"class":54}," \"https\"\n",[374,652,653,656,658,659,661,662,723,725,726,29],{},[377,654,655],{},"Move deploy-specific values to environment variables",[381,657],{},"Keep secrets and environment-specific endpoints out of source code.",[381,660],{},"Typical variables:",[31,663,665],{"className":33,"code":664,"language":35,"meta":36,"style":36},"export FLASK_CONFIG=development\nexport SECRET_KEY='replace-me'\nexport DATABASE_URL='postgresql:\u002F\u002Fuser:pass@localhost\u002Fdbname'\nexport REDIS_URL='redis:\u002F\u002F127.0.0.1:6379\u002F0'\nexport SMTP_HOST='smtp.example.com'\n",[26,666,667,677,688,699,711],{"__ignoreMap":36},[40,668,669,671,673,675],{"class":42,"line":43},[40,670,300],{"class":79},[40,672,304],{"class":303},[40,674,307],{"class":79},[40,676,310],{"class":303},[40,678,679,681,683,685],{"class":42,"line":58},[40,680,300],{"class":79},[40,682,318],{"class":303},[40,684,307],{"class":79},[40,686,687],{"class":54},"'replace-me'\n",[40,689,690,692,694,696],{"class":42,"line":66},[40,691,300],{"class":79},[40,693,331],{"class":303},[40,695,307],{"class":79},[40,697,698],{"class":54},"'postgresql:\u002F\u002Fuser:pass@localhost\u002Fdbname'\n",[40,700,701,703,706,708],{"class":42,"line":73},[40,702,300],{"class":79},[40,704,705],{"class":303}," REDIS_URL",[40,707,307],{"class":79},[40,709,710],{"class":54},"'redis:\u002F\u002F127.0.0.1:6379\u002F0'\n",[40,712,713,715,718,720],{"class":42,"line":92},[40,714,300],{"class":79},[40,716,717],{"class":303}," SMTP_HOST",[40,719,307],{"class":79},[40,721,722],{"class":54},"'smtp.example.com'\n",[381,724],{},"For secret handling patterns, see ",[727,728,730],"a",{"href":729},"\u002Fdeploy\u002Fflask-environment-variables-and-secrets-setup","Flask Environment Variables and Secrets Setup",[374,732,733,736,738,739],{},[377,734,735],{},"Implement an app factory",[381,737],{},"Map the selected environment string to the correct config class.",[31,740,742],{"className":386,"code":741,"language":342,"meta":36,"style":36},"# myapp\u002F__init__.py\nfrom flask import Flask\nfrom config import DevelopmentConfig, StagingConfig, ProductionConfig\n\nCONFIG_MAP = {\n    \"development\": DevelopmentConfig,\n    \"staging\": StagingConfig,\n    \"production\": ProductionConfig,\n}\n\ndef create_app(config_name=\"production\"):\n    app = Flask(__name__)\n    config_class = CONFIG_MAP.get(config_name)\n    if config_class is None:\n        raise RuntimeError(f\"Invalid FLASK_CONFIG value: {config_name}\")\n\n    app.config.from_object(config_class)\n\n    @app.get(\"\u002Fhealth\")\n    def health():\n        return {\"status\": \"ok\", \"env\": app.config.get(\"ENV_NAME\")}\n\n    return app\n",[26,743,744,749,762,774,778,788,796,804,812,817,821,839,854,867,883,913,917,922,926,938,949,980,984],{"__ignoreMap":36},[40,745,746],{"class":42,"line":43},[40,747,748],{"class":394},"# myapp\u002F__init__.py\n",[40,750,751,754,757,759],{"class":42,"line":58},[40,752,753],{"class":79},"from",[40,755,756],{"class":303}," flask ",[40,758,400],{"class":79},[40,760,761],{"class":303}," Flask\n",[40,763,764,766,769,771],{"class":42,"line":66},[40,765,753],{"class":79},[40,767,768],{"class":303}," config ",[40,770,400],{"class":79},[40,772,773],{"class":303}," DevelopmentConfig, StagingConfig, ProductionConfig\n",[40,775,776],{"class":42,"line":73},[40,777,70],{"emptyLinePlaceholder":69},[40,779,780,783,785],{"class":42,"line":92},[40,781,782],{"class":50},"CONFIG_MAP",[40,784,426],{"class":79},[40,786,787],{"class":303}," {\n",[40,789,790,793],{"class":42,"line":98},[40,791,792],{"class":54},"    \"development\"",[40,794,795],{"class":303},": DevelopmentConfig,\n",[40,797,798,801],{"class":42,"line":103},[40,799,800],{"class":54},"    \"staging\"",[40,802,803],{"class":303},": StagingConfig,\n",[40,805,806,809],{"class":42,"line":109},[40,807,808],{"class":54},"    \"production\"",[40,810,811],{"class":303},": ProductionConfig,\n",[40,813,814],{"class":42,"line":115},[40,815,816],{"class":303},"}\n",[40,818,819],{"class":42,"line":121},[40,820,70],{"emptyLinePlaceholder":69},[40,822,823,826,829,832,834,837],{"class":42,"line":126},[40,824,825],{"class":79},"def",[40,827,828],{"class":46}," create_app",[40,830,831],{"class":303},"(config_name",[40,833,307],{"class":79},[40,835,836],{"class":54},"\"production\"",[40,838,465],{"class":303},[40,840,841,844,846,849,852],{"class":42,"line":132},[40,842,843],{"class":303},"    app ",[40,845,307],{"class":79},[40,847,848],{"class":303}," Flask(",[40,850,851],{"class":50},"__name__",[40,853,435],{"class":303},[40,855,856,859,861,864],{"class":42,"line":138},[40,857,858],{"class":303},"    config_class ",[40,860,307],{"class":79},[40,862,863],{"class":50}," CONFIG_MAP",[40,865,866],{"class":303},".get(config_name)\n",[40,868,869,872,875,878,881],{"class":42,"line":144},[40,870,871],{"class":79},"    if",[40,873,874],{"class":303}," config_class ",[40,876,877],{"class":79},"is",[40,879,880],{"class":50}," None",[40,882,418],{"class":303},[40,884,885,888,891,893,896,899,902,905,908,911],{"class":42,"line":150},[40,886,887],{"class":79},"        raise",[40,889,890],{"class":50}," RuntimeError",[40,892,459],{"class":303},[40,894,895],{"class":79},"f",[40,897,898],{"class":54},"\"Invalid FLASK_CONFIG value: ",[40,900,901],{"class":50},"{",[40,903,904],{"class":303},"config_name",[40,906,907],{"class":50},"}",[40,909,910],{"class":54},"\"",[40,912,435],{"class":303},[40,914,915],{"class":42,"line":156},[40,916,70],{"emptyLinePlaceholder":69},[40,918,919],{"class":42,"line":161},[40,920,921],{"class":303},"    app.config.from_object(config_class)\n",[40,923,924],{"class":42,"line":167},[40,925,70],{"emptyLinePlaceholder":69},[40,927,928,931,933,936],{"class":42,"line":173},[40,929,930],{"class":46},"    @app.get",[40,932,459],{"class":303},[40,934,935],{"class":54},"\"\u002Fhealth\"",[40,937,435],{"class":303},[40,939,940,943,946],{"class":42,"line":178},[40,941,942],{"class":79},"    def",[40,944,945],{"class":46}," health",[40,947,948],{"class":303},"():\n",[40,950,951,954,957,960,963,966,968,971,974,977],{"class":42,"line":184},[40,952,953],{"class":79},"        return",[40,955,956],{"class":303}," {",[40,958,959],{"class":54},"\"status\"",[40,961,962],{"class":303},": ",[40,964,965],{"class":54},"\"ok\"",[40,967,509],{"class":303},[40,969,970],{"class":54},"\"env\"",[40,972,973],{"class":303},": app.config.get(",[40,975,976],{"class":54},"\"ENV_NAME\"",[40,978,979],{"class":303},")}\n",[40,981,982],{"class":42,"line":190},[40,983,70],{"emptyLinePlaceholder":69},[40,985,986,989],{"class":42,"line":195},[40,987,988],{"class":79},"    return",[40,990,991],{"class":303}," app\n",[374,993,994,997,999,1000,1002,1003],{},[377,995,996],{},"Load the selected config in WSGI",[381,998],{},"Use ",[26,1001,28],{}," as the runtime selector.",[31,1004,1006],{"className":386,"code":1005,"language":342,"meta":36,"style":36},"# wsgi.py\nimport os\nfrom myapp import create_app\n\napp = create_app(os.environ.get(\"FLASK_CONFIG\", \"production\"))\n",[26,1007,1008,1013,1019,1031,1035],{"__ignoreMap":36},[40,1009,1010],{"class":42,"line":43},[40,1011,1012],{"class":394},"# wsgi.py\n",[40,1014,1015,1017],{"class":42,"line":58},[40,1016,400],{"class":79},[40,1018,403],{"class":303},[40,1020,1021,1023,1026,1028],{"class":42,"line":66},[40,1022,753],{"class":79},[40,1024,1025],{"class":303}," myapp ",[40,1027,400],{"class":79},[40,1029,1030],{"class":303}," create_app\n",[40,1032,1033],{"class":42,"line":73},[40,1034,70],{"emptyLinePlaceholder":69},[40,1036,1037,1040,1042,1045,1048,1050,1052],{"class":42,"line":92},[40,1038,1039],{"class":303},"app ",[40,1041,307],{"class":79},[40,1043,1044],{"class":303}," create_app(os.environ.get(",[40,1046,1047],{"class":54},"\"FLASK_CONFIG\"",[40,1049,509],{"class":303},[40,1051,836],{"class":54},[40,1053,1054],{"class":303},"))\n",[374,1056,1057,1060,1062,1063,1065,1066,1088,1090,1091],{},[377,1058,1059],{},"Set safe defaults only for development",[381,1061],{},"Do not define fallback production secrets or production database URLs in Python code.",[381,1064],{},"Good:",[31,1067,1069],{"className":386,"code":1068,"language":342,"meta":36,"style":36},"SQLALCHEMY_DATABASE_URI = os.environ.get(\"DATABASE_URL\", \"sqlite:\u002F\u002F\u002Fdev.db\")\n",[26,1070,1071],{"__ignoreMap":36},[40,1072,1073,1076,1078,1080,1082,1084,1086],{"class":42,"line":43},[40,1074,1075],{"class":50},"SQLALCHEMY_DATABASE_URI",[40,1077,426],{"class":79},[40,1079,429],{"class":303},[40,1081,506],{"class":54},[40,1083,509],{"class":303},[40,1085,512],{"class":54},[40,1087,435],{"class":303},[381,1089],{},"Bad:",[31,1092,1094],{"className":386,"code":1093,"language":342,"meta":36,"style":36},"SQLALCHEMY_DATABASE_URI = os.environ.get(\n    \"DATABASE_URL\",\n    \"postgresql:\u002F\u002Fprod-user:prod-pass@prod-db\u002Fprod\"\n)\n",[26,1095,1096,1105,1113,1118],{"__ignoreMap":36},[40,1097,1098,1100,1102],{"class":42,"line":43},[40,1099,1075],{"class":50},[40,1101,426],{"class":79},[40,1103,1104],{"class":303}," os.environ.get(\n",[40,1106,1107,1110],{"class":42,"line":58},[40,1108,1109],{"class":54},"    \"DATABASE_URL\"",[40,1111,1112],{"class":303},",\n",[40,1114,1115],{"class":42,"line":66},[40,1116,1117],{"class":54},"    \"postgresql:\u002F\u002Fprod-user:prod-pass@prod-db\u002Fprod\"\n",[40,1119,1120],{"class":42,"line":73},[40,1121,435],{"class":303},[374,1123,1124,1127,1129,1130,1207,1209,1210,29],{},[377,1125,1126],{},"Make production config explicit",[381,1128],{},"Production must disable debug and set security-related flags.",[31,1131,1133],{"className":386,"code":1132,"language":342,"meta":36,"style":36},"class ProductionConfig(BaseConfig):\n    DEBUG = False\n    TESTING = False\n    ENV_NAME = \"production\"\n    SQLALCHEMY_DATABASE_URI = os.environ.get(\"DATABASE_URL\")\n    SESSION_COOKIE_SECURE = True\n    REMEMBER_COOKIE_SECURE = True\n    PREFERRED_URL_SCHEME = \"https\"\n",[26,1134,1135,1147,1155,1163,1171,1183,1191,1199],{"__ignoreMap":36},[40,1136,1137,1139,1141,1143,1145],{"class":42,"line":43},[40,1138,412],{"class":79},[40,1140,579],{"class":46},[40,1142,459],{"class":303},[40,1144,462],{"class":46},[40,1146,465],{"class":303},[40,1148,1149,1151,1153],{"class":42,"line":58},[40,1150,470],{"class":50},[40,1152,426],{"class":79},[40,1154,445],{"class":50},[40,1156,1157,1159,1161],{"class":42,"line":66},[40,1158,480],{"class":50},[40,1160,426],{"class":79},[40,1162,445],{"class":50},[40,1164,1165,1167,1169],{"class":42,"line":73},[40,1166,489],{"class":50},[40,1168,426],{"class":79},[40,1170,610],{"class":54},[40,1172,1173,1175,1177,1179,1181],{"class":42,"line":92},[40,1174,499],{"class":50},[40,1176,426],{"class":79},[40,1178,429],{"class":303},[40,1180,506],{"class":54},[40,1182,435],{"class":303},[40,1184,1185,1187,1189],{"class":42,"line":98},[40,1186,627],{"class":50},[40,1188,426],{"class":79},[40,1190,475],{"class":50},[40,1192,1193,1195,1197],{"class":42,"line":103},[40,1194,636],{"class":50},[40,1196,426],{"class":79},[40,1198,475],{"class":50},[40,1200,1201,1203,1205],{"class":42,"line":109},[40,1202,645],{"class":50},[40,1204,426],{"class":79},[40,1206,650],{"class":54},[381,1208],{},"For production-safe defaults, see ",[727,1211,1213],{"href":1212},"\u002Fdeploy\u002Fflask-production-config-basics","Flask Production Config Basics",[374,1215,1216,1219,1221,1222,1242,1244,1245,1279,1281],{},[377,1217,1218],{},"Use per-environment env files only for local convenience",[381,1220],{},"Example local files:",[31,1223,1225],{"className":33,"code":1224,"language":35,"meta":36,"style":36},".env.dev\n.env.staging\n.env.prod\n",[26,1226,1227,1232,1237],{"__ignoreMap":36},[40,1228,1229],{"class":42,"line":43},[40,1230,1231],{"class":46},".env.dev\n",[40,1233,1234],{"class":42,"line":58},[40,1235,1236],{"class":46},".env.staging\n",[40,1238,1239],{"class":42,"line":66},[40,1240,1241],{"class":46},".env.prod\n",[381,1243],{},"Example content:",[31,1246,1248],{"className":33,"code":1247,"language":35,"meta":36,"style":36},"FLASK_CONFIG=staging\nSECRET_KEY=staging-secret\nDATABASE_URL=postgresql:\u002F\u002Fstaging_user:staging_pass@127.0.0.1\u002Fstaging_db\n",[26,1249,1250,1259,1269],{"__ignoreMap":36},[40,1251,1252,1254,1256],{"class":42,"line":43},[40,1253,28],{"class":303},[40,1255,307],{"class":79},[40,1257,1258],{"class":54},"staging\n",[40,1260,1261,1264,1266],{"class":42,"line":58},[40,1262,1263],{"class":303},"SECRET_KEY",[40,1265,307],{"class":79},[40,1267,1268],{"class":54},"staging-secret\n",[40,1270,1271,1274,1276],{"class":42,"line":66},[40,1272,1273],{"class":303},"DATABASE_URL",[40,1275,307],{"class":79},[40,1277,1278],{"class":54},"postgresql:\u002F\u002Fstaging_user:staging_pass@127.0.0.1\u002Fstaging_db\n",[381,1280],{},"Do not commit real secrets to source control.",[374,1283,1284,1287,1289,1290,1292,1293,29,1296,1381,1383,1384,1423,1425,1426,29],{},[377,1285,1286],{},"Set the environment in systemd",[381,1288],{},"For server deployments, define ",[26,1291,28],{}," and required variables in the unit or an ",[26,1294,1295],{},"EnvironmentFile",[31,1297,1301],{"className":1298,"code":1299,"language":1300,"meta":36,"style":36},"language-ini shiki shiki-themes github-light github-dark","# \u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyapp.service\n[Unit]\nDescription=Gunicorn for myapp\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fvar\u002Fwww\u002Fmyapp\nEnvironment=FLASK_CONFIG=production\nEnvironment=SECRET_KEY=replace-with-real-secret\nEnvironment=DATABASE_URL=postgresql:\u002F\u002Fmyapp:strongpass@127.0.0.1\u002Fmyapp\nExecStart=\u002Fvar\u002Fwww\u002Fmyapp\u002Fvenv\u002Fbin\u002Fgunicorn --workers 3 --bind 127.0.0.1:8000 wsgi:app\n\n[Install]\nWantedBy=multi-user.target\n","ini",[26,1302,1303,1308,1313,1318,1323,1327,1332,1337,1342,1347,1352,1357,1362,1367,1371,1376],{"__ignoreMap":36},[40,1304,1305],{"class":42,"line":43},[40,1306,1307],{},"# \u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyapp.service\n",[40,1309,1310],{"class":42,"line":58},[40,1311,1312],{},"[Unit]\n",[40,1314,1315],{"class":42,"line":66},[40,1316,1317],{},"Description=Gunicorn for myapp\n",[40,1319,1320],{"class":42,"line":73},[40,1321,1322],{},"After=network.target\n",[40,1324,1325],{"class":42,"line":92},[40,1326,70],{"emptyLinePlaceholder":69},[40,1328,1329],{"class":42,"line":98},[40,1330,1331],{},"[Service]\n",[40,1333,1334],{"class":42,"line":103},[40,1335,1336],{},"User=www-data\n",[40,1338,1339],{"class":42,"line":109},[40,1340,1341],{},"Group=www-data\n",[40,1343,1344],{"class":42,"line":115},[40,1345,1346],{},"WorkingDirectory=\u002Fvar\u002Fwww\u002Fmyapp\n",[40,1348,1349],{"class":42,"line":121},[40,1350,1351],{},"Environment=FLASK_CONFIG=production\n",[40,1353,1354],{"class":42,"line":126},[40,1355,1356],{},"Environment=SECRET_KEY=replace-with-real-secret\n",[40,1358,1359],{"class":42,"line":132},[40,1360,1361],{},"Environment=DATABASE_URL=postgresql:\u002F\u002Fmyapp:strongpass@127.0.0.1\u002Fmyapp\n",[40,1363,1364],{"class":42,"line":138},[40,1365,1366],{},"ExecStart=\u002Fvar\u002Fwww\u002Fmyapp\u002Fvenv\u002Fbin\u002Fgunicorn --workers 3 --bind 127.0.0.1:8000 wsgi:app\n",[40,1368,1369],{"class":42,"line":144},[40,1370,70],{"emptyLinePlaceholder":69},[40,1372,1373],{"class":42,"line":150},[40,1374,1375],{},"[Install]\n",[40,1377,1378],{"class":42,"line":156},[40,1379,1380],{},"WantedBy=multi-user.target\n",[381,1382],{},"Apply changes:",[31,1385,1387],{"className":33,"code":1386,"language":35,"meta":36,"style":36},"sudo systemctl daemon-reload\nsudo systemctl restart myapp\nsudo systemctl status myapp\n",[26,1388,1389,1400,1412],{"__ignoreMap":36},[40,1390,1391,1394,1397],{"class":42,"line":43},[40,1392,1393],{"class":46},"sudo",[40,1395,1396],{"class":54}," systemctl",[40,1398,1399],{"class":54}," daemon-reload\n",[40,1401,1402,1404,1406,1409],{"class":42,"line":58},[40,1403,1393],{"class":46},[40,1405,1396],{"class":54},[40,1407,1408],{"class":54}," restart",[40,1410,1411],{"class":54}," myapp\n",[40,1413,1414,1416,1418,1421],{"class":42,"line":66},[40,1415,1393],{"class":46},[40,1417,1396],{"class":54},[40,1419,1420],{"class":54}," status",[40,1422,1411],{"class":54},[381,1424],{},"For the full service stack, see ",[727,1427,1429],{"href":1428},"\u002Fdeploy\u002Fdeploy-flask-with-nginx-plus-gunicorn-step-by-step-guide","Deploy Flask with Nginx + Gunicorn (Step-by-Step Guide)",[374,1431,1432,1435,1437,1438,1440,1441,1525,1527,1528],{},[377,1433,1434],{},"Set the environment in Docker or Compose",[381,1436],{},"Pass ",[26,1439,28],{}," and secrets through container runtime variables.",[31,1442,1446],{"className":1443,"code":1444,"language":1445,"meta":36,"style":36},"language-yaml shiki shiki-themes github-light github-dark","services:\n  web:\n    image: myapp:latest\n    environment:\n      FLASK_CONFIG: production\n      SECRET_KEY: ${SECRET_KEY}\n      DATABASE_URL: ${DATABASE_URL}\n    ports:\n      - \"8000:8000\"\n","yaml",[26,1447,1448,1456,1463,1473,1480,1490,1500,1510,1517],{"__ignoreMap":36},[40,1449,1450,1454],{"class":42,"line":43},[40,1451,1453],{"class":1452},"s9eBZ","services",[40,1455,418],{"class":303},[40,1457,1458,1461],{"class":42,"line":58},[40,1459,1460],{"class":1452},"  web",[40,1462,418],{"class":303},[40,1464,1465,1468,1470],{"class":42,"line":66},[40,1466,1467],{"class":1452},"    image",[40,1469,962],{"class":303},[40,1471,1472],{"class":54},"myapp:latest\n",[40,1474,1475,1478],{"class":42,"line":73},[40,1476,1477],{"class":1452},"    environment",[40,1479,418],{"class":303},[40,1481,1482,1485,1487],{"class":42,"line":92},[40,1483,1484],{"class":1452},"      FLASK_CONFIG",[40,1486,962],{"class":303},[40,1488,1489],{"class":54},"production\n",[40,1491,1492,1495,1497],{"class":42,"line":98},[40,1493,1494],{"class":1452},"      SECRET_KEY",[40,1496,962],{"class":303},[40,1498,1499],{"class":54},"${SECRET_KEY}\n",[40,1501,1502,1505,1507],{"class":42,"line":103},[40,1503,1504],{"class":1452},"      DATABASE_URL",[40,1506,962],{"class":303},[40,1508,1509],{"class":54},"${DATABASE_URL}\n",[40,1511,1512,1515],{"class":42,"line":109},[40,1513,1514],{"class":1452},"    ports",[40,1516,418],{"class":303},[40,1518,1519,1522],{"class":42,"line":115},[40,1520,1521],{"class":303},"      - ",[40,1523,1524],{"class":54},"\"8000:8000\"\n",[381,1526],{},"Validate effective config:",[31,1529,1531],{"className":33,"code":1530,"language":35,"meta":36,"style":36},"docker compose config\ndocker exec -it \u003Ccontainer_name> \u002Fbin\u002Fsh -c 'printenv | sort | egrep \"FLASK_CONFIG|DATABASE_URL|SECRET_KEY\"'\n",[26,1532,1533,1544],{"__ignoreMap":36},[40,1534,1535,1538,1541],{"class":42,"line":43},[40,1536,1537],{"class":46},"docker",[40,1539,1540],{"class":54}," compose",[40,1542,1543],{"class":54}," config\n",[40,1545,1546,1548,1551,1554,1557,1560,1563,1566,1569,1571],{"class":42,"line":58},[40,1547,1537],{"class":46},[40,1549,1550],{"class":54}," exec",[40,1552,1553],{"class":50}," -it",[40,1555,1556],{"class":79}," \u003C",[40,1558,1559],{"class":54},"container_nam",[40,1561,1562],{"class":303},"e",[40,1564,1565],{"class":79},">",[40,1567,1568],{"class":54}," \u002Fbin\u002Fsh",[40,1570,345],{"class":50},[40,1572,1573],{"class":54}," 'printenv | sort | egrep \"FLASK_CONFIG|DATABASE_URL|SECRET_KEY\"'\n",[374,1575,1576,1579,1581,1582],{},[377,1577,1578],{},"Validate the loaded config before deploy",[381,1580],{},"Confirm the application is using the expected environment and settings.",[31,1583,1585],{"className":33,"code":1584,"language":35,"meta":36,"style":36},"python -c \"from myapp import create_app; app=create_app('production'); print(app.config.get('ENV_NAME'), app.config.get('DEBUG'), app.config.get('SQLALCHEMY_DATABASE_URI'))\"\n",[26,1586,1587],{"__ignoreMap":36},[40,1588,1589,1591,1593],{"class":42,"line":43},[40,1590,342],{"class":46},[40,1592,345],{"class":50},[40,1594,1595],{"class":54}," \"from myapp import create_app; app=create_app('production'); print(app.config.get('ENV_NAME'), app.config.get('DEBUG'), app.config.get('SQLALCHEMY_DATABASE_URI'))\"\n",[374,1597,1598,1601,1603,1604,1622,1624],{},[377,1599,1600],{},"Keep staging close to production",[381,1602],{},"Staging should use:",[1605,1606,1607,1610,1613,1616,1619],"ul",{},[374,1608,1609],{},"the same WSGI server class",[374,1611,1612],{},"similar Nginx behavior",[374,1614,1615],{},"the same database engine type",[374,1617,1618],{},"HTTPS where possible",[374,1620,1621],{},"similar middleware and extension setup",[381,1623],{},"Do not treat staging like development.",[374,1626,1627,1634,1636,1637,1639],{},[377,1628,1629,1630,1633],{},"Avoid deprecated ",[26,1631,1632],{},"FLASK_ENV"," assumptions",[381,1635],{},"Use your own selector such as ",[26,1638,28],{},". Treat that variable as the single source of truth for environment selection.",[374,1641,1642,1645,1647,1648],{},[377,1643,1644],{},"Add a startup confirmation log",[381,1646],{},"Log only the environment name, never secrets.",[31,1649,1651],{"className":386,"code":1650,"language":342,"meta":36,"style":36},"import logging\n\ndef create_app(config_name=\"production\"):\n    app = Flask(__name__)\n    app.config.from_object(CONFIG_MAP[config_name])\n    app.logger.setLevel(logging.INFO)\n    app.logger.info(\"Starting app with config: %s\", app.config.get(\"ENV_NAME\"))\n    return app\n",[26,1652,1653,1660,1664,1678,1690,1700,1710,1730],{"__ignoreMap":36},[40,1654,1655,1657],{"class":42,"line":43},[40,1656,400],{"class":79},[40,1658,1659],{"class":303}," logging\n",[40,1661,1662],{"class":42,"line":58},[40,1663,70],{"emptyLinePlaceholder":69},[40,1665,1666,1668,1670,1672,1674,1676],{"class":42,"line":66},[40,1667,825],{"class":79},[40,1669,828],{"class":46},[40,1671,831],{"class":303},[40,1673,307],{"class":79},[40,1675,836],{"class":54},[40,1677,465],{"class":303},[40,1679,1680,1682,1684,1686,1688],{"class":42,"line":73},[40,1681,843],{"class":303},[40,1683,307],{"class":79},[40,1685,848],{"class":303},[40,1687,851],{"class":50},[40,1689,435],{"class":303},[40,1691,1692,1695,1697],{"class":42,"line":92},[40,1693,1694],{"class":303},"    app.config.from_object(",[40,1696,782],{"class":50},[40,1698,1699],{"class":303},"[config_name])\n",[40,1701,1702,1705,1708],{"class":42,"line":98},[40,1703,1704],{"class":303},"    app.logger.setLevel(logging.",[40,1706,1707],{"class":50},"INFO",[40,1709,435],{"class":303},[40,1711,1712,1715,1718,1721,1723,1726,1728],{"class":42,"line":103},[40,1713,1714],{"class":303},"    app.logger.info(",[40,1716,1717],{"class":54},"\"Starting app with config: ",[40,1719,1720],{"class":50},"%s",[40,1722,910],{"class":54},[40,1724,1725],{"class":303},", app.config.get(",[40,1727,976],{"class":54},[40,1729,1054],{"class":303},[40,1731,1732,1734],{"class":42,"line":109},[40,1733,988],{"class":79},[40,1735,991],{"class":303},[374,1737,1738],{},[377,1739,1740],{},"Document the config selection flow",[18,1742,1744],{"id":1743},"common-causes","Common Causes",[1605,1746,1747,1759,1767,1779,1785,1794,1804],{},[374,1748,1749,1752,1753,1755,1756,1758],{},[377,1750,1751],{},"Production runs with development settings"," → ",[26,1754,28],{}," is unset or defaults to development → set ",[26,1757,357],{}," in systemd, Docker, or deployment variables.",[374,1760,1761,1752,1764,1766],{},[377,1762,1763],{},"Wrong database used after deploy",[26,1765,1273],{}," is shared or hardcoded across environments → define a unique database URL per environment and verify it at startup.",[374,1768,1769,1772,1773,509,1775,1778],{},[377,1770,1771],{},"Secrets missing in staging or production"," → environment variables are not loaded by systemd or the container runtime → use ",[26,1774,1295],{},[26,1776,1777],{},"env_file",", or secret injection and restart the service.",[374,1780,1781,1784],{},[377,1782,1783],{},"App behaves differently between staging and production"," → staging does not mirror production closely enough → align WSGI server, proxy headers, HTTPS behavior, and extension settings.",[374,1786,1787,1790,1791,29],{},[377,1788,1789],{},"Debug toolbar or verbose error pages visible in production"," → debug-related extensions are enabled globally → load them only in ",[26,1792,1793],{},"DevelopmentConfig",[374,1795,1796,1799,1800,1803],{},[377,1797,1798],{},"Config changes do not apply after deploy"," → Gunicorn or systemd still uses old environment values → run ",[26,1801,1802],{},"daemon-reload",", restart services, and verify active environment variables.",[374,1805,1806,1809,1810,1813],{},[377,1807,1808],{},"Cookies fail only in production"," → secure cookie settings are missing or inconsistent with HTTPS termination → set ",[26,1811,1812],{},"SESSION_COOKIE_SECURE=True"," and verify proxy\u002FHTTPS behavior.",[18,1815,1817],{"id":1816},"debugging-section","Debugging Section",[14,1819,1820],{},"Check runtime environment variables first:",[31,1822,1824],{"className":33,"code":1823,"language":35,"meta":36,"style":36},"printenv | sort | egrep 'FLASK_CONFIG|SECRET_KEY|DATABASE_URL|REDIS_URL'\npython -c \"import os; print(os.environ.get('FLASK_CONFIG'), os.environ.get('DATABASE_URL'))\"\n",[26,1825,1826,1845],{"__ignoreMap":36},[40,1827,1828,1831,1834,1837,1839,1842],{"class":42,"line":43},[40,1829,1830],{"class":46},"printenv",[40,1832,1833],{"class":79}," |",[40,1835,1836],{"class":46}," sort",[40,1838,1833],{"class":79},[40,1840,1841],{"class":46}," egrep",[40,1843,1844],{"class":54}," 'FLASK_CONFIG|SECRET_KEY|DATABASE_URL|REDIS_URL'\n",[40,1846,1847,1849,1851],{"class":42,"line":58},[40,1848,342],{"class":46},[40,1850,345],{"class":50},[40,1852,1853],{"class":54}," \"import os; print(os.environ.get('FLASK_CONFIG'), os.environ.get('DATABASE_URL'))\"\n",[14,1855,1856],{},"Validate loaded Flask config directly:",[31,1858,1859],{"className":33,"code":1584,"language":35,"meta":36,"style":36},[26,1860,1861],{"__ignoreMap":36},[40,1862,1863,1865,1867],{"class":42,"line":43},[40,1864,342],{"class":46},[40,1866,345],{"class":50},[40,1868,1595],{"class":54},[14,1870,1871],{},"Inspect systemd configuration:",[31,1873,1875],{"className":33,"code":1874,"language":35,"meta":36,"style":36},"systemctl cat myapp\nsystemctl show myapp --property=Environment\nsudo systemctl daemon-reload && sudo systemctl restart myapp\nsudo journalctl -u myapp -n 100 --no-pager\n",[26,1876,1877,1887,1900,1920],{"__ignoreMap":36},[40,1878,1879,1882,1885],{"class":42,"line":43},[40,1880,1881],{"class":46},"systemctl",[40,1883,1884],{"class":54}," cat",[40,1886,1411],{"class":54},[40,1888,1889,1891,1894,1897],{"class":42,"line":58},[40,1890,1881],{"class":46},[40,1892,1893],{"class":54}," show",[40,1895,1896],{"class":54}," myapp",[40,1898,1899],{"class":50}," --property=Environment\n",[40,1901,1902,1904,1906,1909,1912,1914,1916,1918],{"class":42,"line":66},[40,1903,1393],{"class":46},[40,1905,1396],{"class":54},[40,1907,1908],{"class":54}," daemon-reload",[40,1910,1911],{"class":303}," && ",[40,1913,1393],{"class":46},[40,1915,1396],{"class":54},[40,1917,1408],{"class":54},[40,1919,1411],{"class":54},[40,1921,1922,1924,1927,1930,1932,1935,1938],{"class":42,"line":73},[40,1923,1393],{"class":46},[40,1925,1926],{"class":54}," journalctl",[40,1928,1929],{"class":50}," -u",[40,1931,1896],{"class":54},[40,1933,1934],{"class":50}," -n",[40,1936,1937],{"class":50}," 100",[40,1939,1940],{"class":50}," --no-pager\n",[14,1942,1943],{},"Validate Gunicorn startup config:",[31,1945,1947],{"className":33,"code":1946,"language":35,"meta":36,"style":36},"gunicorn --check-config 'wsgi:app'\n",[26,1948,1949],{"__ignoreMap":36},[40,1950,1951,1954,1957],{"class":42,"line":43},[40,1952,1953],{"class":46},"gunicorn",[40,1955,1956],{"class":50}," --check-config",[40,1958,1959],{"class":54}," 'wsgi:app'\n",[14,1961,1962],{},"Inspect containers:",[31,1964,1965],{"className":33,"code":1530,"language":35,"meta":36,"style":36},[26,1966,1967,1975],{"__ignoreMap":36},[40,1968,1969,1971,1973],{"class":42,"line":43},[40,1970,1537],{"class":46},[40,1972,1540],{"class":54},[40,1974,1543],{"class":54},[40,1976,1977,1979,1981,1983,1985,1987,1989,1991,1993,1995],{"class":42,"line":58},[40,1978,1537],{"class":46},[40,1980,1550],{"class":54},[40,1982,1553],{"class":50},[40,1984,1556],{"class":79},[40,1986,1559],{"class":54},[40,1988,1562],{"class":303},[40,1990,1565],{"class":79},[40,1992,1568],{"class":54},[40,1994,345],{"class":50},[40,1996,1573],{"class":54},[14,1998,1999],{},"What to look for:",[1605,2001,2002,2007,2017,2022,2025,2028],{},[374,2003,2004,2006],{},[26,2005,28],{}," matches the target environment",[374,2008,2009,2012,2013,2016],{},[26,2010,2011],{},"DEBUG"," is ",[26,2014,2015],{},"False"," outside development",[374,2018,2019,2021],{},[26,2020,1273],{}," points to the correct database",[374,2023,2024],{},"startup logs show the expected environment",[374,2026,2027],{},"systemd or container config includes the intended variables",[374,2029,2030,2031,2034],{},"Gunicorn loads ",[26,2032,2033],{},"wsgi:app"," without import\u002Fconfig errors",[14,2036,2037,2038,29],{},"If the app starts but requests fail upstream, also check ",[727,2039,2041],{"href":2040},"\u002Ffix-issues\u002Ffix-flask-502-bad-gateway-step-by-step-guide","Fix Flask 502 Bad Gateway (Step-by-Step Guide)",[18,2043,2045],{"id":2044},"checklist","Checklist",[1605,2047,2050,2062,2071,2077,2083,2089,2095,2101],{"className":2048},[2049],"contains-task-list",[374,2051,2054,2058,2059,2061],{"className":2052},[2053],"task-list-item",[2055,2056],"input",{"disabled":69,"type":2057},"checkbox"," ",[26,2060,28],{}," is set explicitly in each environment",[374,2063,2065,2067,2068],{"className":2064},[2053],[2055,2066],{"disabled":69,"type":2057}," Production does not run with ",[26,2069,2070],{},"DEBUG=True",[374,2072,2074,2076],{"className":2073},[2053],[2055,2075],{"disabled":69,"type":2057}," Each environment uses a different database or isolated schema",[374,2078,2080,2082],{"className":2079},[2053],[2055,2081],{"disabled":69,"type":2057}," Secrets are loaded from environment variables or a secret manager",[374,2084,2086,2088],{"className":2085},[2053],[2055,2087],{"disabled":69,"type":2057}," Staging behavior matches production closely enough to catch deploy issues",[374,2090,2092,2094],{"className":2091},[2053],[2055,2093],{"disabled":69,"type":2057}," A startup check confirms the active config before serving traffic",[374,2096,2098,2100],{"className":2097},[2053],[2055,2099],{"disabled":69,"type":2057}," systemd or container definitions include the required variables",[374,2102,2104,2106],{"className":2103},[2053],[2055,2105],{"disabled":69,"type":2057}," No production secrets are hardcoded in source files",[18,2108,2110],{"id":2109},"related-guides","Related Guides",[1605,2112,2113,2117,2121,2125],{},[374,2114,2115],{},[727,2116,1429],{"href":1428},[374,2118,2119],{},[727,2120,730],{"href":729},[374,2122,2123],{},[727,2124,1213],{"href":1212},[374,2126,2127],{},[727,2128,2130],{"href":2129},"\u002Fchecklist\u002Fflask-production-checklist-everything-you-must-do","Flask Production Checklist (Everything You Must Do)",[18,2132,2134],{"id":2133},"faq","FAQ",[14,2136,2137,2140,2142],{},[377,2138,2139],{},"Q: What is the minimum environment split for Flask?",[381,2141],{},"\nA: Use at least development and production. Add staging if you deploy changes before production.",[14,2144,2145,2148,2150],{},[377,2146,2147],{},"Q: Should staging and production share secrets?",[381,2149],{},"\nA: No. Use separate secrets and usually separate databases or isolated schemas.",[14,2152,2153,2156,2158],{},[377,2154,2155],{},"Q: Can I store config in Python classes and env vars together?",[381,2157],{},"\nA: Yes. Keep structure in Python classes and inject sensitive or deploy-specific values through environment variables.",[14,2160,2161,2164,2166],{},[377,2162,2163],{},"Q: How do I confirm the correct config loaded?",[381,2165],{},"\nA: Print a non-sensitive startup log showing the selected environment and inspect service environment variables.",[14,2168,2169,2175,2177],{},[377,2170,2171,2172,2174],{},"Q: Should staging use ",[26,2173,2070],{},"?",[381,2176],{},"\nA: No. Keep staging close to production and debug through logs and monitoring.",[14,2179,2180,2185,2187,2188,2190],{},[377,2181,2182,2183,2174],{},"Q: Should I use ",[26,2184,1632],{},[381,2186],{},"\nA: Prefer your own config selector such as ",[26,2189,28],{}," and explicit environment variables.",[14,2192,2193,2196,2198,2199,2201],{},[377,2194,2195],{},"Q: Where should production secrets live?",[381,2197],{},"\nA: In a systemd ",[26,2200,1295],{},", container secrets, or a managed secret store, not in source control.",[18,2203,2205],{"id":2204},"final-takeaway","Final Takeaway",[14,2207,2208],{},"Use one config entry point, separate classes per environment, and environment variables for all secrets and deploy-specific values. The key requirement is explicit selection of development, staging, or production at runtime and validation before traffic reaches the app.",[2210,2211,2212],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":36,"searchDepth":58,"depth":58,"links":2214},[2215,2216,2217,2218,2219,2220,2221,2222,2223],{"id":20,"depth":58,"text":21},{"id":361,"depth":58,"text":362},{"id":368,"depth":58,"text":369},{"id":1743,"depth":58,"text":1744},{"id":1816,"depth":58,"text":1817},{"id":2044,"depth":58,"text":2045},{"id":2109,"depth":58,"text":2110},{"id":2133,"depth":58,"text":2134},{"id":2204,"depth":58,"text":2205},"Complete guide on flask config environments: dev vs staging vs production for Flask production environments.","md",{"ogTitle":5,"ogDescription":2224,"twitterCard":2227,"robots":2228,"canonical":2229},"summary_large_image","index, follow","https:\u002F\u002Fflask-deployment.com\u002Freference\u002Fflask-config-environments-dev-vs-staging-vs-production","\u002Freference\u002Fflask-config-environments-dev-vs-staging-vs-production",{"title":5,"description":2224},"reference\u002Fflask-config-environments-dev-vs-staging-vs-production","2a4n1uxCj68EIsh6hiqIbOxmCpv6it4mcdLikDTeZOE",1776805765080]