[{"data":1,"prerenderedAt":1623},["ShallowReactive",2],{"\u002Ffix-issues\u002Fflask-database-connection-errors-in-production":3},{"id":4,"title":5,"body":6,"description":1613,"extension":1614,"meta":1615,"navigation":67,"path":1619,"seo":1620,"stem":1621,"__hash__":1622},"content\u002Ffix-issues\u002Fflask-database-connection-errors-in-production.md","Flask Database Connection Errors in Production",{"type":7,"value":8,"toc":1602},"minimark",[9,13,17,22,25,244,255,259,262,265,284,287,291,1121,1125,1212,1216,1219,1379,1382,1410,1414,1489,1493,1515,1519,1530,1544,1564,1575,1583,1591,1595,1598],[10,11,5],"h1",{"id":12},"flask-database-connection-errors-in-production",[14,15,16],"p",{},"If you're seeing database connection failures in a Flask production app, this guide shows you how to identify the failing layer and fix it step-by-step. It covers credentials, environment variables, PostgreSQL reachability, SSL settings, and app startup validation so requests can connect reliably again.",[18,19,21],"h2",{"id":20},"quick-fix-quick-setup","Quick Fix \u002F Quick Setup",[14,23,24],{},"Run these checks from the application server:",[26,27,32],"pre",{"className":28,"code":29,"language":30,"meta":31,"style":31},"language-bash shiki shiki-themes github-light github-dark","# 1) Verify the app has the expected database URL\necho \"$DATABASE_URL\"\n\n# 2) Test TCP reachability to PostgreSQL from the app server\nnc -vz DB_HOST 5432\n\n# 3) Test login directly with psql\nPGPASSWORD='DB_PASSWORD' psql -h DB_HOST -U DB_USER -d DB_NAME -p 5432 -c 'select 1;'\n\n# 4) If using SQLAlchemy, verify the driver is installed\npython3 -c \"import psycopg2; print('psycopg2 OK')\"\n\n# 5) Check the running Flask\u002FGunicorn service environment and logs\nsudo systemctl show gunicorn --property=Environment\nsudo journalctl -u gunicorn -n 100 --no-pager\n\n# 6) Restart after fixing config\nsudo systemctl restart gunicorn\n","bash","",[33,34,35,44,62,69,75,91,96,102,147,152,158,169,174,180,198,220,225,231],"code",{"__ignoreMap":31},[36,37,40],"span",{"class":38,"line":39},"line",1,[36,41,43],{"class":42},"sJ8bj","# 1) Verify the app has the expected database URL\n",[36,45,47,51,55,59],{"class":38,"line":46},2,[36,48,50],{"class":49},"sj4cs","echo",[36,52,54],{"class":53},"sZZnC"," \"",[36,56,58],{"class":57},"sVt8B","$DATABASE_URL",[36,60,61],{"class":53},"\"\n",[36,63,65],{"class":38,"line":64},3,[36,66,68],{"emptyLinePlaceholder":67},true,"\n",[36,70,72],{"class":38,"line":71},4,[36,73,74],{"class":42},"# 2) Test TCP reachability to PostgreSQL from the app server\n",[36,76,78,82,85,88],{"class":38,"line":77},5,[36,79,81],{"class":80},"sScJk","nc",[36,83,84],{"class":49}," -vz",[36,86,87],{"class":53}," DB_HOST",[36,89,90],{"class":49}," 5432\n",[36,92,94],{"class":38,"line":93},6,[36,95,68],{"emptyLinePlaceholder":67},[36,97,99],{"class":38,"line":98},7,[36,100,101],{"class":42},"# 3) Test login directly with psql\n",[36,103,105,108,112,115,118,121,123,126,129,132,135,138,141,144],{"class":38,"line":104},8,[36,106,107],{"class":57},"PGPASSWORD",[36,109,111],{"class":110},"szBVR","=",[36,113,114],{"class":53},"'DB_PASSWORD'",[36,116,117],{"class":80}," psql",[36,119,120],{"class":49}," -h",[36,122,87],{"class":53},[36,124,125],{"class":49}," -U",[36,127,128],{"class":53}," DB_USER",[36,130,131],{"class":49}," -d",[36,133,134],{"class":53}," DB_NAME",[36,136,137],{"class":49}," -p",[36,139,140],{"class":49}," 5432",[36,142,143],{"class":49}," -c",[36,145,146],{"class":53}," 'select 1;'\n",[36,148,150],{"class":38,"line":149},9,[36,151,68],{"emptyLinePlaceholder":67},[36,153,155],{"class":38,"line":154},10,[36,156,157],{"class":42},"# 4) If using SQLAlchemy, verify the driver is installed\n",[36,159,161,164,166],{"class":38,"line":160},11,[36,162,163],{"class":80},"python3",[36,165,143],{"class":49},[36,167,168],{"class":53}," \"import psycopg2; print('psycopg2 OK')\"\n",[36,170,172],{"class":38,"line":171},12,[36,173,68],{"emptyLinePlaceholder":67},[36,175,177],{"class":38,"line":176},13,[36,178,179],{"class":42},"# 5) Check the running Flask\u002FGunicorn service environment and logs\n",[36,181,183,186,189,192,195],{"class":38,"line":182},14,[36,184,185],{"class":80},"sudo",[36,187,188],{"class":53}," systemctl",[36,190,191],{"class":53}," show",[36,193,194],{"class":53}," gunicorn",[36,196,197],{"class":49}," --property=Environment\n",[36,199,201,203,206,209,211,214,217],{"class":38,"line":200},15,[36,202,185],{"class":80},[36,204,205],{"class":53}," journalctl",[36,207,208],{"class":49}," -u",[36,210,194],{"class":53},[36,212,213],{"class":49}," -n",[36,215,216],{"class":49}," 100",[36,218,219],{"class":49}," --no-pager\n",[36,221,223],{"class":38,"line":222},16,[36,224,68],{"emptyLinePlaceholder":67},[36,226,228],{"class":38,"line":227},17,[36,229,230],{"class":42},"# 6) Restart after fixing config\n",[36,232,234,236,238,241],{"class":38,"line":233},18,[36,235,185],{"class":80},[36,237,188],{"class":53},[36,239,240],{"class":53}," restart",[36,242,243],{"class":53}," gunicorn\n",[14,245,246,247,250,251,254],{},"If direct ",[33,248,249],{},"psql"," login fails, fix database host, port, credentials, ",[33,252,253],{},"pg_hba.conf",", firewall rules, or managed database allowlists before changing Flask code.",[18,256,258],{"id":257},"whats-happening","What’s Happening",[14,260,261],{},"Production database errors usually happen before or during request handling when Flask or SQLAlchemy cannot open a valid connection.",[14,263,264],{},"The failure is usually in one of these layers:",[266,267,268,272,275,278,281],"ul",{},[269,270,271],"li",{},"application config is missing or wrong",[269,273,274],{},"DSN format is invalid",[269,276,277],{},"network or DNS cannot reach PostgreSQL",[269,279,280],{},"PostgreSQL rejects authentication or access",[269,282,283],{},"SSL\u002FTLS is required but not enabled",[14,285,286],{},"Gunicorn may show this as worker boot failures, 500 responses, timeouts, or intermittent errors under load.",[18,288,290],{"id":289},"step-by-step-guide","Step-by-Step Guide",[292,293,294,373,519,562,631,680,760,844,911,958,992,1072],"ol",{},[269,295,296,300,303,304,338,340,341],{},[297,298,299],"strong",{},"Confirm the exact error from logs",[301,302],"br",{},"Check Gunicorn and app logs first.",[26,305,307],{"className":28,"code":306,"language":30,"meta":31,"style":31},"sudo journalctl -u gunicorn -n 100 --no-pager\nsudo journalctl -u gunicorn -f\n",[33,308,309,325],{"__ignoreMap":31},[36,310,311,313,315,317,319,321,323],{"class":38,"line":39},[36,312,185],{"class":80},[36,314,205],{"class":53},[36,316,208],{"class":49},[36,318,194],{"class":53},[36,320,213],{"class":49},[36,322,216],{"class":49},[36,324,219],{"class":49},[36,326,327,329,331,333,335],{"class":38,"line":46},[36,328,185],{"class":80},[36,330,205],{"class":53},[36,332,208],{"class":49},[36,334,194],{"class":53},[36,336,337],{"class":49}," -f\n",[301,339],{},"Look for errors such as:",[266,342,343,348,353,358,363,368],{},[269,344,345],{},[33,346,347],{},"could not connect to server",[269,349,350],{},[33,351,352],{},"password authentication failed",[269,354,355],{},[33,356,357],{},"database does not exist",[269,359,360],{},[33,361,362],{},"sslmode required",[269,364,365],{},[33,366,367],{},"timeout expired",[269,369,370],{},[33,371,372],{},"sqlalchemy.exc.OperationalError",[269,374,375,378,380,381,409,411,412,447,449,450,452,453,475,477,478,492,494,495],{},[297,376,377],{},"Verify the database settings loaded into the running service",[301,379],{},"Check whether Gunicorn has the expected environment.",[26,382,384],{"className":28,"code":383,"language":30,"meta":31,"style":31},"sudo systemctl show gunicorn --property=Environment\nsudo systemctl cat gunicorn\n",[33,385,386,398],{"__ignoreMap":31},[36,387,388,390,392,394,396],{"class":38,"line":39},[36,389,185],{"class":80},[36,391,188],{"class":53},[36,393,191],{"class":53},[36,395,194],{"class":53},[36,397,197],{"class":49},[36,399,400,402,404,407],{"class":38,"line":46},[36,401,185],{"class":80},[36,403,188],{"class":53},[36,405,406],{"class":53}," cat",[36,408,243],{"class":53},[301,410],{},"Validate:",[266,413,414,419,424,429,434,439,444],{},[269,415,416],{},[33,417,418],{},"DATABASE_URL",[269,420,421],{},[33,422,423],{},"DB_HOST",[269,425,426],{},[33,427,428],{},"DB_PORT",[269,430,431],{},[33,432,433],{},"DB_NAME",[269,435,436],{},[33,437,438],{},"DB_USER",[269,440,441],{},[33,442,443],{},"DB_PASSWORD",[269,445,446],{},"SSL-related variables",[301,448],{},"If variables are missing in systemd, add them to the service or environment file.",[301,451],{},"Example systemd override:",[26,454,458],{"className":455,"code":456,"language":457,"meta":31,"style":31},"language-ini shiki shiki-themes github-light github-dark","[Service]\nEnvironment=\"DATABASE_URL=postgresql+psycopg2:\u002F\u002Fappuser:strongpass@db.example.com:5432\u002Fappdb\"\nEnvironment=\"FLASK_ENV=production\"\n","ini",[33,459,460,465,470],{"__ignoreMap":31},[36,461,462],{"class":38,"line":39},[36,463,464],{},"[Service]\n",[36,466,467],{"class":38,"line":46},[36,468,469],{},"Environment=\"DATABASE_URL=postgresql+psycopg2:\u002F\u002Fappuser:strongpass@db.example.com:5432\u002Fappdb\"\n",[36,471,472],{"class":38,"line":64},[36,473,474],{},"Environment=\"FLASK_ENV=production\"\n",[301,476],{},"Or use an environment file:",[26,479,481],{"className":455,"code":480,"language":457,"meta":31,"style":31},"[Service]\nEnvironmentFile=\u002Fetc\u002Fflask\u002Fmyapp.env\n",[33,482,483,487],{"__ignoreMap":31},[36,484,485],{"class":38,"line":39},[36,486,464],{},[36,488,489],{"class":38,"line":46},[36,490,491],{},"EnvironmentFile=\u002Fetc\u002Fflask\u002Fmyapp.env\n",[301,493],{},"Then reload and restart:",[26,496,498],{"className":28,"code":497,"language":30,"meta":31,"style":31},"sudo systemctl daemon-reload\nsudo systemctl restart gunicorn\n",[33,499,500,509],{"__ignoreMap":31},[36,501,502,504,506],{"class":38,"line":39},[36,503,185],{"class":80},[36,505,188],{"class":53},[36,507,508],{"class":53}," daemon-reload\n",[36,510,511,513,515,517],{"class":38,"line":46},[36,512,185],{"class":80},[36,514,188],{"class":53},[36,516,240],{"class":53},[36,518,243],{"class":53},[269,520,521,524,526,527,535,537,538,541,542,541,545,548,549,552,553,555,556],{},[297,522,523],{},"Validate the DSN format",[301,525],{},"A correct PostgreSQL SQLAlchemy URL looks like this:",[26,528,533],{"className":529,"code":531,"language":532,"meta":31},[530],"language-text","postgresql+psycopg2:\u002F\u002Fappuser:strongpass@db.example.com:5432\u002Fappdb\n","text",[33,534,531],{"__ignoreMap":31},[301,536],{},"If the password contains special characters, URL-encode them. Characters like ",[33,539,540],{},"@",", ",[33,543,544],{},":",[33,546,547],{},"\u002F",", and ",[33,550,551],{},"#"," can break parsing.",[301,554],{},"Example:",[26,557,560],{"className":558,"code":559,"language":532,"meta":31},[530],"password: myP@ss:word\nencoded : myP%40ss%3Aword\n",[33,561,559],{"__ignoreMap":31},[269,563,564,567,569,570,593,595,596,611,613,614],{},[297,565,566],{},"Test DNS and network reachability",[301,568],{},"Confirm the database hostname resolves correctly.",[26,571,573],{"className":28,"code":572,"language":30,"meta":31,"style":31},"getent hosts DB_HOST\ndig DB_HOST\n",[33,574,575,586],{"__ignoreMap":31},[36,576,577,580,583],{"class":38,"line":39},[36,578,579],{"class":80},"getent",[36,581,582],{"class":53}," hosts",[36,584,585],{"class":53}," DB_HOST\n",[36,587,588,591],{"class":38,"line":46},[36,589,590],{"class":80},"dig",[36,592,585],{"class":53},[301,594],{},"Then test the port:",[26,597,599],{"className":28,"code":598,"language":30,"meta":31,"style":31},"nc -vz DB_HOST 5432\n",[33,600,601],{"__ignoreMap":31},[36,602,603,605,607,609],{"class":38,"line":39},[36,604,81],{"class":80},[36,606,84],{"class":49},[36,608,87],{"class":53},[36,610,90],{"class":49},[301,612],{},"If this fails, check:",[266,615,616,619,622,625,628],{},[269,617,618],{},"cloud security groups",[269,620,621],{},"firewall rules",[269,623,624],{},"VPC or private network routing",[269,626,627],{},"wrong hostname",[269,629,630],{},"managed database allowlists",[269,632,633,636,638,639,641,642,677,679],{},[297,634,635],{},"Test authentication outside Flask",[301,637],{},"Use ",[33,640,249],{}," from the application host.",[26,643,645],{"className":28,"code":644,"language":30,"meta":31,"style":31},"PGPASSWORD='DB_PASSWORD' psql -h DB_HOST -U DB_USER -d DB_NAME -p 5432 -c 'select 1;'\n",[33,646,647],{"__ignoreMap":31},[36,648,649,651,653,655,657,659,661,663,665,667,669,671,673,675],{"class":38,"line":39},[36,650,107],{"class":57},[36,652,111],{"class":110},[36,654,114],{"class":53},[36,656,117],{"class":80},[36,658,120],{"class":49},[36,660,87],{"class":53},[36,662,125],{"class":49},[36,664,128],{"class":53},[36,666,131],{"class":49},[36,668,134],{"class":53},[36,670,137],{"class":49},[36,672,140],{"class":49},[36,674,143],{"class":49},[36,676,146],{"class":53},[301,678],{},"If this fails, the problem is not Flask-specific.",[269,681,682,685,687,688,707,709,710,727,729,730],{},[297,683,684],{},"Check PostgreSQL access control and privileges",[301,686],{},"Verify on the database side:",[266,689,690,693,696,699,702],{},[269,691,692],{},"the user exists",[269,694,695],{},"the database exists",[269,697,698],{},"the user can connect",[269,700,701],{},"the user has required privileges",[269,703,704,706],{},[33,705,253],{}," allows the application host or subnet",[301,708],{},"Example checks from PostgreSQL:",[26,711,715],{"className":712,"code":713,"language":714,"meta":31,"style":31},"language-sql shiki shiki-themes github-light github-dark","\\du\n\\l\n","sql",[33,716,717,722],{"__ignoreMap":31},[36,718,719],{"class":38,"line":39},[36,720,721],{},"\\du\n",[36,723,724],{"class":38,"line":46},[36,725,726],{},"\\l\n",[301,728],{},"Example grants:",[26,731,733],{"className":712,"code":732,"language":714,"meta":31,"style":31},"GRANT CONNECT ON DATABASE appdb TO appuser;\nGRANT USAGE ON SCHEMA public TO appuser;\nGRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO appuser;\nALTER DEFAULT PRIVILEGES IN SCHEMA public\nGRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO appuser;\n",[33,734,735,740,745,750,755],{"__ignoreMap":31},[36,736,737],{"class":38,"line":39},[36,738,739],{},"GRANT CONNECT ON DATABASE appdb TO appuser;\n",[36,741,742],{"class":38,"line":46},[36,743,744],{},"GRANT USAGE ON SCHEMA public TO appuser;\n",[36,746,747],{"class":38,"line":64},[36,748,749],{},"GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO appuser;\n",[36,751,752],{"class":38,"line":71},[36,753,754],{},"ALTER DEFAULT PRIVILEGES IN SCHEMA public\n",[36,756,757],{"class":38,"line":77},[36,758,759],{},"GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO appuser;\n",[269,761,762,765,767,768,770,771,777,779,780,837,839,840,843],{},[297,763,764],{},"Enable SSL if the provider requires it",[301,766],{},"Many managed PostgreSQL services require TLS.",[301,769],{},"In a DSN:",[26,772,775],{"className":773,"code":774,"language":532,"meta":31},[530],"postgresql+psycopg2:\u002F\u002Fappuser:strongpass@db.example.com:5432\u002Fappdb?sslmode=require\n",[33,776,774],{"__ignoreMap":31},[301,778],{},"Or with SQLAlchemy config:",[26,781,785],{"className":782,"code":783,"language":784,"meta":31,"style":31},"language-python shiki shiki-themes github-light github-dark","SQLALCHEMY_DATABASE_URI = \"postgresql+psycopg2:\u002F\u002Fappuser:strongpass@db.example.com:5432\u002Fappdb\"\nSQLALCHEMY_ENGINE_OPTIONS = {\n    \"connect_args\": {\n        \"sslmode\": \"require\"\n    }\n}\n","python",[33,786,787,798,808,816,827,832],{"__ignoreMap":31},[36,788,789,792,795],{"class":38,"line":39},[36,790,791],{"class":49},"SQLALCHEMY_DATABASE_URI",[36,793,794],{"class":110}," =",[36,796,797],{"class":53}," \"postgresql+psycopg2:\u002F\u002Fappuser:strongpass@db.example.com:5432\u002Fappdb\"\n",[36,799,800,803,805],{"class":38,"line":46},[36,801,802],{"class":49},"SQLALCHEMY_ENGINE_OPTIONS",[36,804,794],{"class":110},[36,806,807],{"class":57}," {\n",[36,809,810,813],{"class":38,"line":64},[36,811,812],{"class":53},"    \"connect_args\"",[36,814,815],{"class":57},": {\n",[36,817,818,821,824],{"class":38,"line":71},[36,819,820],{"class":53},"        \"sslmode\"",[36,822,823],{"class":57},": ",[36,825,826],{"class":53},"\"require\"\n",[36,828,829],{"class":38,"line":77},[36,830,831],{"class":57},"    }\n",[36,833,834],{"class":38,"line":93},[36,835,836],{"class":57},"}\n",[301,838],{},"If your provider requires certificates, add ",[33,841,842],{},"sslrootcert"," or provider-specific options.",[269,845,846,849,851,852,866,868,869,893,895,896],{},[297,847,848],{},"Verify the Python database driver in the Gunicorn environment",[301,850],{},"Check the interpreter used by the app.",[26,853,855],{"className":28,"code":854,"language":30,"meta":31,"style":31},"python3 -c \"import psycopg2; print(psycopg2.__version__)\"\n",[33,856,857],{"__ignoreMap":31},[36,858,859,861,863],{"class":38,"line":39},[36,860,163],{"class":80},[36,862,143],{"class":49},[36,864,865],{"class":53}," \"import psycopg2; print(psycopg2.__version__)\"\n",[301,867],{},"If missing, install it in the same virtual environment used by Gunicorn.",[26,870,872],{"className":28,"code":871,"language":30,"meta":31,"style":31},"source \u002Fpath\u002Fto\u002Fvenv\u002Fbin\u002Factivate\npip install psycopg2-binary\n",[33,873,874,882],{"__ignoreMap":31},[36,875,876,879],{"class":38,"line":39},[36,877,878],{"class":49},"source",[36,880,881],{"class":53}," \u002Fpath\u002Fto\u002Fvenv\u002Fbin\u002Factivate\n",[36,883,884,887,890],{"class":38,"line":46},[36,885,886],{"class":80},"pip",[36,888,889],{"class":53}," install",[36,891,892],{"class":53}," psycopg2-binary\n",[301,894],{},"Then restart Gunicorn:",[26,897,899],{"className":28,"code":898,"language":30,"meta":31,"style":31},"sudo systemctl restart gunicorn\n",[33,900,901],{"__ignoreMap":31},[36,902,903,905,907,909],{"class":38,"line":39},[36,904,185],{"class":80},[36,906,188],{"class":53},[36,908,240],{"class":53},[36,910,243],{"class":53},[269,912,913,916,918,919,921,922,949,951,952,957],{},[297,914,915],{},"Confirm Flask loads configuration during startup",[301,917],{},"If environment variables work in your shell but not in production, Gunicorn is likely starting without them.",[301,920],{},"Validate the service file and environment path:",[26,923,925],{"className":28,"code":924,"language":30,"meta":31,"style":31},"sudo systemctl cat gunicorn\nsudo systemctl show gunicorn --property=Environment\n",[33,926,927,937],{"__ignoreMap":31},[36,928,929,931,933,935],{"class":38,"line":39},[36,930,185],{"class":80},[36,932,188],{"class":53},[36,934,406],{"class":53},[36,936,243],{"class":53},[36,938,939,941,943,945,947],{"class":38,"line":46},[36,940,185],{"class":80},[36,942,188],{"class":53},[36,944,191],{"class":53},[36,946,194],{"class":53},[36,948,197],{"class":49},[301,950],{},"If needed, fix systemd environment loading. See ",[953,954,956],"a",{"href":955},"\u002Ffix-issues\u002Fflask-environment-variables-not-loading-in-production","Flask Environment Variables Not Loading in Production",".",[269,959,960,963,965,966,968,969,985,987,988,957],{},[297,961,962],{},"Check schema and migrations after connectivity works",[301,964],{},"A reachable database can still fail if required tables do not exist.",[301,967],{},"Run your migration workflow, for example:",[26,970,972],{"className":28,"code":971,"language":30,"meta":31,"style":31},"flask db upgrade\n",[33,973,974],{"__ignoreMap":31},[36,975,976,979,982],{"class":38,"line":39},[36,977,978],{"class":80},"flask",[36,980,981],{"class":53}," db",[36,983,984],{"class":53}," upgrade\n",[301,986],{},"Then verify tables exist. If migrations are the problem, use ",[953,989,991],{"href":990},"\u002Ffix-issues\u002Fflask-migrations-not-applied-fix-guide","Flask Migrations Not Applied (Fix Guide)",[269,993,994,997,999,1000,555,1002,1066,1068,1069,957],{},[297,995,996],{},"Review SQLAlchemy pool settings for load-related failures",[301,998],{},"If the problem appears only under traffic, tune connection handling.",[301,1001],{},[26,1003,1005],{"className":782,"code":1004,"language":784,"meta":31,"style":31},"SQLALCHEMY_ENGINE_OPTIONS = {\n    \"pool_pre_ping\": True,\n    \"pool_recycle\": 1800,\n    \"pool_size\": 10,\n    \"max_overflow\": 20\n}\n",[33,1006,1007,1015,1028,1040,1052,1062],{"__ignoreMap":31},[36,1008,1009,1011,1013],{"class":38,"line":39},[36,1010,802],{"class":49},[36,1012,794],{"class":110},[36,1014,807],{"class":57},[36,1016,1017,1020,1022,1025],{"class":38,"line":46},[36,1018,1019],{"class":53},"    \"pool_pre_ping\"",[36,1021,823],{"class":57},[36,1023,1024],{"class":49},"True",[36,1026,1027],{"class":57},",\n",[36,1029,1030,1033,1035,1038],{"class":38,"line":64},[36,1031,1032],{"class":53},"    \"pool_recycle\"",[36,1034,823],{"class":57},[36,1036,1037],{"class":49},"1800",[36,1039,1027],{"class":57},[36,1041,1042,1045,1047,1050],{"class":38,"line":71},[36,1043,1044],{"class":53},"    \"pool_size\"",[36,1046,823],{"class":57},[36,1048,1049],{"class":49},"10",[36,1051,1027],{"class":57},[36,1053,1054,1057,1059],{"class":38,"line":77},[36,1055,1056],{"class":53},"    \"max_overflow\"",[36,1058,823],{"class":57},[36,1060,1061],{"class":49},"20\n",[36,1063,1064],{"class":38,"line":93},[36,1065,836],{"class":57},[301,1067],{},"Also confirm PostgreSQL is not hitting ",[33,1070,1071],{},"max_connections",[269,1073,1074,1077,1079,1080,1107,1109,1110],{},[297,1075,1076],{},"Restart and verify end-to-end",[301,1078],{},"Restart services:",[26,1081,1083],{"className":28,"code":1082,"language":30,"meta":31,"style":31},"sudo systemctl restart gunicorn\nsudo systemctl reload nginx\n",[33,1084,1085,1095],{"__ignoreMap":31},[36,1086,1087,1089,1091,1093],{"class":38,"line":39},[36,1088,185],{"class":80},[36,1090,188],{"class":53},[36,1092,240],{"class":53},[36,1094,243],{"class":53},[36,1096,1097,1099,1101,1104],{"class":38,"line":46},[36,1098,185],{"class":80},[36,1100,188],{"class":53},[36,1102,1103],{"class":53}," reload",[36,1105,1106],{"class":53}," nginx\n",[301,1108],{},"Then send a request that performs a real database read or write and confirm:",[266,1111,1112,1115,1118],{},[269,1113,1114],{},"no 500 responses",[269,1116,1117],{},"no Gunicorn worker exits",[269,1119,1120],{},"no new DB auth or timeout errors",[18,1122,1124],{"id":1123},"common-causes","Common Causes",[266,1126,1127,1136,1150,1160,1168,1174,1184,1194,1200,1206],{},[269,1128,1129,1135],{},[297,1130,1131,1132,1134],{},"Wrong ",[33,1133,418],{}," or malformed SQLAlchemy DSN"," → Flask points to the wrong host, database, or cannot parse the URL → Correct the DSN and URL-encode credentials.",[269,1137,1138,1141,1142,1145,1146,1149],{},[297,1139,1140],{},"Environment variables not loaded in systemd"," → Gunicorn starts without database settings → Add ",[33,1143,1144],{},"Environment="," or ",[33,1147,1148],{},"EnvironmentFile="," and reload systemd.",[269,1151,1152,1155,1156,1159],{},[297,1153,1154],{},"Database host unreachable"," → Firewall, security group, DNS, or routing blocks TCP access → Open port ",[33,1157,1158],{},"5432"," and validate hostname resolution.",[269,1161,1162,1165,1166,957],{},[297,1163,1164],{},"PostgreSQL authentication failed"," → Username, password, or auth method is wrong → Reset credentials or update ",[33,1167,253],{},[269,1169,1170,1173],{},[297,1171,1172],{},"Database does not exist or user lacks privileges"," → Connection opens but target DB cannot be used → Create the database and grant privileges.",[269,1175,1176,1179,1180,1183],{},[297,1177,1178],{},"SSL\u002FTLS required by provider"," → Non-TLS sessions are rejected → Add ",[33,1181,1182],{},"sslmode=require"," or provider certificate settings.",[269,1185,1186,1189,1190,1193],{},[297,1187,1188],{},"Python database driver missing"," → SQLAlchemy cannot open a real DB connection → Install ",[33,1191,1192],{},"psycopg2-binary"," or the required driver in the active virtualenv.",[269,1195,1196,1199],{},[297,1197,1198],{},"Migrations not applied"," → App connects but fails on missing tables or columns → Run migrations before serving traffic.",[269,1201,1202,1205],{},[297,1203,1204],{},"Too many open connections"," → Database rejects new sessions under load → Tune SQLAlchemy pooling and database connection limits.",[269,1207,1208,1211],{},[297,1209,1210],{},"DNS resolution mismatch"," → Hostname resolves to the wrong IP → Fix DNS records or use the correct provider endpoint.",[18,1213,1215],{"id":1214},"debugging-section","Debugging Section",[14,1217,1218],{},"Check the following commands in order:",[26,1220,1222],{"className":28,"code":1221,"language":30,"meta":31,"style":31},"echo \"$DATABASE_URL\"\nsudo systemctl show gunicorn --property=Environment\nsudo systemctl cat gunicorn\nsudo journalctl -u gunicorn -n 100 --no-pager\nsudo journalctl -u gunicorn -f\nsudo journalctl -u nginx -n 100 --no-pager\ngetent hosts DB_HOST\ndig DB_HOST\nnc -vz DB_HOST 5432\nPGPASSWORD='DB_PASSWORD' psql -h DB_HOST -U DB_USER -d DB_NAME -p 5432 -c 'select 1;'\npython3 -c \"import psycopg2; print(psycopg2.__version__)\"\nss -tulpn | grep 5432\n",[33,1223,1224,1234,1246,1256,1272,1284,1301,1309,1315,1325,1355,1363],{"__ignoreMap":31},[36,1225,1226,1228,1230,1232],{"class":38,"line":39},[36,1227,50],{"class":49},[36,1229,54],{"class":53},[36,1231,58],{"class":57},[36,1233,61],{"class":53},[36,1235,1236,1238,1240,1242,1244],{"class":38,"line":46},[36,1237,185],{"class":80},[36,1239,188],{"class":53},[36,1241,191],{"class":53},[36,1243,194],{"class":53},[36,1245,197],{"class":49},[36,1247,1248,1250,1252,1254],{"class":38,"line":64},[36,1249,185],{"class":80},[36,1251,188],{"class":53},[36,1253,406],{"class":53},[36,1255,243],{"class":53},[36,1257,1258,1260,1262,1264,1266,1268,1270],{"class":38,"line":71},[36,1259,185],{"class":80},[36,1261,205],{"class":53},[36,1263,208],{"class":49},[36,1265,194],{"class":53},[36,1267,213],{"class":49},[36,1269,216],{"class":49},[36,1271,219],{"class":49},[36,1273,1274,1276,1278,1280,1282],{"class":38,"line":77},[36,1275,185],{"class":80},[36,1277,205],{"class":53},[36,1279,208],{"class":49},[36,1281,194],{"class":53},[36,1283,337],{"class":49},[36,1285,1286,1288,1290,1292,1295,1297,1299],{"class":38,"line":93},[36,1287,185],{"class":80},[36,1289,205],{"class":53},[36,1291,208],{"class":49},[36,1293,1294],{"class":53}," nginx",[36,1296,213],{"class":49},[36,1298,216],{"class":49},[36,1300,219],{"class":49},[36,1302,1303,1305,1307],{"class":38,"line":98},[36,1304,579],{"class":80},[36,1306,582],{"class":53},[36,1308,585],{"class":53},[36,1310,1311,1313],{"class":38,"line":104},[36,1312,590],{"class":80},[36,1314,585],{"class":53},[36,1316,1317,1319,1321,1323],{"class":38,"line":149},[36,1318,81],{"class":80},[36,1320,84],{"class":49},[36,1322,87],{"class":53},[36,1324,90],{"class":49},[36,1326,1327,1329,1331,1333,1335,1337,1339,1341,1343,1345,1347,1349,1351,1353],{"class":38,"line":154},[36,1328,107],{"class":57},[36,1330,111],{"class":110},[36,1332,114],{"class":53},[36,1334,117],{"class":80},[36,1336,120],{"class":49},[36,1338,87],{"class":53},[36,1340,125],{"class":49},[36,1342,128],{"class":53},[36,1344,131],{"class":49},[36,1346,134],{"class":53},[36,1348,137],{"class":49},[36,1350,140],{"class":49},[36,1352,143],{"class":49},[36,1354,146],{"class":53},[36,1356,1357,1359,1361],{"class":38,"line":160},[36,1358,163],{"class":80},[36,1360,143],{"class":49},[36,1362,865],{"class":53},[36,1364,1365,1368,1371,1374,1377],{"class":38,"line":171},[36,1366,1367],{"class":80},"ss",[36,1369,1370],{"class":49}," -tulpn",[36,1372,1373],{"class":110}," |",[36,1375,1376],{"class":80}," grep",[36,1378,90],{"class":49},[14,1380,1381],{},"What to look for:",[266,1383,1384,1387,1390,1393,1399,1404,1407],{},[269,1385,1386],{},"systemd is loading the expected environment",[269,1388,1389],{},"Gunicorn is using the correct virtual environment",[269,1391,1392],{},"database hostname resolves correctly",[269,1394,1395,1396,1398],{},"port ",[33,1397,1158],{}," is reachable",[269,1400,1401,1403],{},[33,1402,249],{}," works from the same host",[269,1405,1406],{},"PostgreSQL logs show auth failures, SSL mismatch, or connection limits",[269,1408,1409],{},"app startup fails before serving requests",[18,1411,1413],{"id":1412},"checklist","Checklist",[266,1415,1418,1433,1439,1445,1453,1459,1465,1471,1477,1483],{"className":1416},[1417],"contains-task-list",[269,1419,1422,1426,1427,1145,1429,1432],{"className":1420},[1421],"task-list-item",[1423,1424],"input",{"disabled":67,"type":1425},"checkbox"," ",[33,1428,418],{},[33,1430,1431],{},"DB_*"," variables match the intended production database",[269,1434,1436,1438],{"className":1435},[1421],[1423,1437],{"disabled":67,"type":1425}," Gunicorn systemd service loads the same environment variables you expect",[269,1440,1442,1444],{"className":1441},[1421],[1423,1443],{"disabled":67,"type":1425}," The app server can reach the database host and port",[269,1446,1448,1426,1450,1452],{"className":1447},[1421],[1423,1449],{"disabled":67,"type":1425},[33,1451,249],{}," login works from the application server",[269,1454,1456,1458],{"className":1455},[1421],[1423,1457],{"disabled":67,"type":1425}," Required Python database driver is installed in the active virtual environment",[269,1460,1462,1464],{"className":1461},[1421],[1423,1463],{"disabled":67,"type":1425}," PostgreSQL user, database, and privileges are correct",[269,1466,1468,1470],{"className":1467},[1421],[1423,1469],{"disabled":67,"type":1425}," SSL mode matches database provider requirements",[269,1472,1474,1476],{"className":1473},[1421],[1423,1475],{"disabled":67,"type":1425}," Migrations have been applied successfully",[269,1478,1480,1482],{"className":1479},[1421],[1423,1481],{"disabled":67,"type":1425}," Gunicorn restarts cleanly without worker boot errors",[269,1484,1486,1488],{"className":1485},[1421],[1423,1487],{"disabled":67,"type":1425}," A live request that reads or writes the database succeeds",[18,1490,1492],{"id":1491},"related-guides","Related Guides",[266,1494,1495,1501,1505,1509],{},[269,1496,1497],{},[953,1498,1500],{"href":1499},"\u002Fdeploy\u002Fdeploy-flask-with-nginx-plus-gunicorn-step-by-step-guide","Deploy Flask with Nginx + Gunicorn (Step-by-Step Guide)",[269,1502,1503],{},[953,1504,956],{"href":955},[269,1506,1507],{},[953,1508,991],{"href":990},[269,1510,1511],{},[953,1512,1514],{"href":1513},"\u002Fchecklist\u002Fflask-production-checklist-everything-you-must-do","Flask Production Checklist (Everything You Must Do)",[18,1516,1518],{"id":1517},"faq","FAQ",[14,1520,1521,1524,1526,1527,957],{},[297,1522,1523],{},"Q: Why does the app work in my shell but fail under Gunicorn?",[301,1525],{},"\nA: systemd usually does not inherit your shell environment. Add database variables to the service unit or an ",[33,1528,1529],{},"EnvironmentFile",[14,1531,1532,1535,1537,1538,1540,1541,1543],{},[297,1533,1534],{},"Q: How do I know whether the issue is Flask or PostgreSQL?",[301,1536],{},"\nA: Test with ",[33,1539,249],{}," from the application server. If ",[33,1542,249],{}," fails, the issue is outside Flask. If it works, inspect Flask config, drivers, and SQLAlchemy settings.",[14,1545,1546,1552,1554,1555,541,1557,541,1559,548,1561,1563],{},[297,1547,1548,1549,1551],{},"Q: Do special characters in the password break ",[33,1550,418],{},"?",[301,1553],{},"\nA: Yes. URL-encode characters like ",[33,1556,540],{},[33,1558,544],{},[33,1560,547],{},[33,1562,551],{}," when embedding credentials in a DSN.",[14,1565,1566,1569,1571,1572,1574],{},[297,1567,1568],{},"Q: Do I need SSL for PostgreSQL in production?",[301,1570],{},"\nA: Often yes for managed databases. If the provider requires TLS, set ",[33,1573,1182],{}," or the certificate options they document.",[14,1576,1577,1580,1582],{},[297,1578,1579],{},"Q: Can Gunicorn worker boot errors be caused by database problems?",[301,1581],{},"\nA: Yes. If the app creates a database connection during startup and that fails, Gunicorn workers may exit immediately.",[14,1584,1585,1588,1590],{},[297,1586,1587],{},"Q: What should I check after fixing connectivity?",[301,1589],{},"\nA: Apply migrations, restart Gunicorn, and send a request that performs a real database read or write.",[18,1592,1594],{"id":1593},"final-takeaway","Final Takeaway",[14,1596,1597],{},"Most Flask production database errors come from config loading, reachability, authentication, SSL, or schema state. Test the connection outside Flask first, then verify the running Gunicorn environment, and only then adjust application code.",[1599,1600,1601],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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 .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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);}",{"title":31,"searchDepth":46,"depth":46,"links":1603},[1604,1605,1606,1607,1608,1609,1610,1611,1612],{"id":20,"depth":46,"text":21},{"id":257,"depth":46,"text":258},{"id":289,"depth":46,"text":290},{"id":1123,"depth":46,"text":1124},{"id":1214,"depth":46,"text":1215},{"id":1412,"depth":46,"text":1413},{"id":1491,"depth":46,"text":1492},{"id":1517,"depth":46,"text":1518},{"id":1593,"depth":46,"text":1594},"Complete guide on flask database connection errors in production for Flask production environments.","md",{"ogTitle":5,"ogDescription":1613,"twitterCard":1616,"robots":1617,"canonical":1618},"summary_large_image","index, follow","https:\u002F\u002Fflask-deployment.com\u002Ffix-issues\u002Fflask-database-connection-errors-in-production","\u002Ffix-issues\u002Fflask-database-connection-errors-in-production",{"title":5,"description":1613},"fix-issues\u002Fflask-database-connection-errors-in-production","-aRmxpMndmlpZx5cyeoLB0H1EXb-TfOgq15Up-yWFoA",1776805765845]