[{"data":1,"prerenderedAt":1359},["ShallowReactive",2],{"\u002Foptimize\u002Fzero-downtime-flask-deployment-gunicorn-reload-strategy":3},{"id":4,"title":5,"body":6,"description":1349,"extension":1350,"meta":1351,"navigation":238,"path":1355,"seo":1356,"stem":1357,"__hash__":1358},"content\u002Foptimize\u002Fzero-downtime-flask-deployment-gunicorn-reload-strategy.md","Zero Downtime Flask Deployment (Gunicorn Reload Strategy)",{"type":7,"value":8,"toc":1329},"minimark",[9,13,17,22,25,128,143,147,150,154,810,814,894,898,901,906,1101,1105,1140,1157,1161,1238,1245,1249,1269,1273,1277,1282,1286,1289,1293,1296,1300,1303,1307,1318,1322,1325],[10,11,5],"h1",{"id":12},"zero-downtime-flask-deployment-gunicorn-reload-strategy",[14,15,16],"p",{},"If you're trying to deploy Flask updates without dropping requests, this guide shows you how to reload Gunicorn safely behind Nginx. The goal is to replace application code or workers in production while keeping the site available and validating that the new release is serving traffic.",[18,19,21],"h2",{"id":20},"quick-fix-quick-setup","Quick Fix \u002F Quick Setup",[14,23,24],{},"Use this if your Flask app is already running behind Nginx and Gunicorn with a systemd service that supports reloads:",[26,27,32],"pre",{"className":28,"code":29,"language":30,"meta":31,"style":31},"language-bash shiki shiki-themes github-light github-dark","cd \u002Fsrv\u002Fmyapp\nsource .venv\u002Fbin\u002Factivate\npip install -r requirements.txt\nflask db upgrade\nsudo systemctl reload myapp\nsudo systemctl status myapp --no-pager\ncurl -I http:\u002F\u002F127.0.0.1:8000\n","bash","",[33,34,35,48,57,73,85,100,116],"code",{"__ignoreMap":31},[36,37,40,44],"span",{"class":38,"line":39},"line",1,[36,41,43],{"class":42},"sj4cs","cd",[36,45,47],{"class":46},"sZZnC"," \u002Fsrv\u002Fmyapp\n",[36,49,51,54],{"class":38,"line":50},2,[36,52,53],{"class":42},"source",[36,55,56],{"class":46}," .venv\u002Fbin\u002Factivate\n",[36,58,60,64,67,70],{"class":38,"line":59},3,[36,61,63],{"class":62},"sScJk","pip",[36,65,66],{"class":46}," install",[36,68,69],{"class":42}," -r",[36,71,72],{"class":46}," requirements.txt\n",[36,74,76,79,82],{"class":38,"line":75},4,[36,77,78],{"class":62},"flask",[36,80,81],{"class":46}," db",[36,83,84],{"class":46}," upgrade\n",[36,86,88,91,94,97],{"class":38,"line":87},5,[36,89,90],{"class":62},"sudo",[36,92,93],{"class":46}," systemctl",[36,95,96],{"class":46}," reload",[36,98,99],{"class":46}," myapp\n",[36,101,103,105,107,110,113],{"class":38,"line":102},6,[36,104,90],{"class":62},[36,106,93],{"class":46},[36,108,109],{"class":46}," status",[36,111,112],{"class":46}," myapp",[36,114,115],{"class":42}," --no-pager\n",[36,117,119,122,125],{"class":38,"line":118},7,[36,120,121],{"class":62},"curl",[36,123,124],{"class":42}," -I",[36,126,127],{"class":46}," http:\u002F\u002F127.0.0.1:8000\n",[14,129,130,131,134,135,138,139,142],{},"Use ",[33,132,133],{},"systemctl reload"," only if your Gunicorn systemd unit defines ",[33,136,137],{},"ExecReload"," with a ",[33,140,141],{},"HUP"," signal. This performs a graceful worker reload instead of a full stop\u002Fstart in simple setups.",[18,144,146],{"id":145},"whats-happening","What’s Happening",[14,148,149],{},"Gunicorn can reload workers gracefully so existing requests finish while new workers start with updated code. Nginx continues proxying to Gunicorn during the reload, which avoids the connection gap caused by a stop\u002Fstart restart. Zero downtime depends on enough workers, correct signal handling, healthy startup, and backward-compatible database changes.",[18,151,153],{"id":152},"step-by-step-guide","Step-by-Step Guide",[155,156,157,195,326,345,372,425,462,516,547,580,620,649,694,722,747,760],"ol",{},[158,159,160,164,167,168],"li",{},[161,162,163],"strong",{},"Confirm the current deployment model",[165,166],"br",{},"Verify that Flask is already running behind Nginx and Gunicorn with a systemd service.",[26,169,171],{"className":28,"code":170,"language":30,"meta":31,"style":31},"sudo systemctl status myapp --no-pager\nsudo nginx -t\n",[33,172,173,185],{"__ignoreMap":31},[36,174,175,177,179,181,183],{"class":38,"line":39},[36,176,90],{"class":62},[36,178,93],{"class":46},[36,180,109],{"class":46},[36,182,112],{"class":46},[36,184,115],{"class":42},[36,186,187,189,192],{"class":38,"line":50},[36,188,90],{"class":62},[36,190,191],{"class":46}," nginx",[36,193,194],{"class":42}," -t\n",[158,196,197,200,202,203,205,206,208,209,211,212],{},[161,198,199],{},"Configure Gunicorn for graceful reload",[165,201],{},"Edit the systemd unit and define ",[33,204,137],{}," so systemd sends ",[33,207,141],{}," to the Gunicorn master process.",[165,210],{},"Example unit:",[26,213,217],{"className":214,"code":215,"language":216,"meta":31,"style":31},"language-ini shiki shiki-themes github-light github-dark","[Unit]\nDescription=Gunicorn for myapp\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fsrv\u002Fmyapp\u002Fcurrent\nEnvironmentFile=\u002Fetc\u002Fmyapp.env\nExecStart=\u002Fsrv\u002Fmyapp\u002F.venv\u002Fbin\u002Fgunicorn \\\n    --workers 3 \\\n    --bind unix:\u002Frun\u002Fmyapp.sock \\\n    wsgi:app\nExecReload=\u002Fbin\u002Fkill -HUP $MAINPID\nRestart=always\nRestartSec=3\n\n[Install]\nWantedBy=multi-user.target\n","ini",[33,218,219,224,229,234,240,245,250,255,261,267,273,279,285,291,297,303,309,314,320],{"__ignoreMap":31},[36,220,221],{"class":38,"line":39},[36,222,223],{},"[Unit]\n",[36,225,226],{"class":38,"line":50},[36,227,228],{},"Description=Gunicorn for myapp\n",[36,230,231],{"class":38,"line":59},[36,232,233],{},"After=network.target\n",[36,235,236],{"class":38,"line":75},[36,237,239],{"emptyLinePlaceholder":238},true,"\n",[36,241,242],{"class":38,"line":87},[36,243,244],{},"[Service]\n",[36,246,247],{"class":38,"line":102},[36,248,249],{},"User=www-data\n",[36,251,252],{"class":38,"line":118},[36,253,254],{},"Group=www-data\n",[36,256,258],{"class":38,"line":257},8,[36,259,260],{},"WorkingDirectory=\u002Fsrv\u002Fmyapp\u002Fcurrent\n",[36,262,264],{"class":38,"line":263},9,[36,265,266],{},"EnvironmentFile=\u002Fetc\u002Fmyapp.env\n",[36,268,270],{"class":38,"line":269},10,[36,271,272],{},"ExecStart=\u002Fsrv\u002Fmyapp\u002F.venv\u002Fbin\u002Fgunicorn \\\n",[36,274,276],{"class":38,"line":275},11,[36,277,278],{},"    --workers 3 \\\n",[36,280,282],{"class":38,"line":281},12,[36,283,284],{},"    --bind unix:\u002Frun\u002Fmyapp.sock \\\n",[36,286,288],{"class":38,"line":287},13,[36,289,290],{},"    wsgi:app\n",[36,292,294],{"class":38,"line":293},14,[36,295,296],{},"ExecReload=\u002Fbin\u002Fkill -HUP $MAINPID\n",[36,298,300],{"class":38,"line":299},15,[36,301,302],{},"Restart=always\n",[36,304,306],{"class":38,"line":305},16,[36,307,308],{},"RestartSec=3\n",[36,310,312],{"class":38,"line":311},17,[36,313,239],{"emptyLinePlaceholder":238},[36,315,317],{"class":38,"line":316},18,[36,318,319],{},"[Install]\n",[36,321,323],{"class":38,"line":322},19,[36,324,325],{},"WantedBy=multi-user.target\n",[158,327,328,331],{},[161,329,330],{},"Reload systemd if the unit changed",[26,332,334],{"className":28,"code":333,"language":30,"meta":31,"style":31},"sudo systemctl daemon-reload\n",[33,335,336],{"__ignoreMap":31},[36,337,338,340,342],{"class":38,"line":39},[36,339,90],{"class":62},[36,341,93],{"class":46},[36,343,344],{"class":46}," daemon-reload\n",[158,346,347,350,352,353,355,356,365,367,368,371],{},[161,348,349],{},"Run more than one Gunicorn worker",[165,351],{},"Zero-downtime reloads are not reliable with a single worker.",[165,354],{},"Example:",[26,357,359],{"className":214,"code":358,"language":216,"meta":31,"style":31},"ExecStart=\u002Fsrv\u002Fmyapp\u002F.venv\u002Fbin\u002Fgunicorn --workers 3 --bind unix:\u002Frun\u002Fmyapp.sock wsgi:app\n",[33,360,361],{"__ignoreMap":31},[36,362,363],{"class":38,"line":39},[36,364,358],{},[165,366],{},"Minimum practical baseline: ",[33,369,370],{},"--workers 2",".",[158,373,374,377,379,380,382,383],{},[161,375,376],{},"Keep the upstream target stable",[165,378],{},"Do not change the Unix socket path or TCP port during a normal release. Nginx should continue pointing to the same upstream.",[165,381],{},"Example Nginx upstream:",[26,384,388],{"className":385,"code":386,"language":387,"meta":31,"style":31},"language-nginx shiki shiki-themes github-light github-dark","location \u002F {\n    proxy_pass http:\u002F\u002Funix:\u002Frun\u002Fmyapp.sock;\n    proxy_set_header Host $host;\n    proxy_set_header X-Real-IP $remote_addr;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_set_header X-Forwarded-Proto $scheme;\n}\n","nginx",[33,389,390,395,400,405,410,415,420],{"__ignoreMap":31},[36,391,392],{"class":38,"line":39},[36,393,394],{},"location \u002F {\n",[36,396,397],{"class":38,"line":50},[36,398,399],{},"    proxy_pass http:\u002F\u002Funix:\u002Frun\u002Fmyapp.sock;\n",[36,401,402],{"class":38,"line":59},[36,403,404],{},"    proxy_set_header Host $host;\n",[36,406,407],{"class":38,"line":75},[36,408,409],{},"    proxy_set_header X-Real-IP $remote_addr;\n",[36,411,412],{"class":38,"line":87},[36,413,414],{},"    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n",[36,416,417],{"class":38,"line":102},[36,418,419],{},"    proxy_set_header X-Forwarded-Proto $scheme;\n",[36,421,422],{"class":38,"line":118},[36,423,424],{},"}\n",[158,426,427,430,432,433,355,435,443,445,446],{},[161,428,429],{},"Use a stable release path if you deploy versioned releases",[165,431],{},"A release-directory layout makes rollback easier.",[165,434],{},[26,436,441],{"className":437,"code":439,"language":440,"meta":31},[438],"language-text","\u002Fsrv\u002Fmyapp\u002Freleases\u002F2026-04-21\n\u002Fsrv\u002Fmyapp\u002Fcurrent -> \u002Fsrv\u002Fmyapp\u002Freleases\u002F2026-04-21\n","text",[33,442,439],{"__ignoreMap":31},[165,444],{},"Verify the active release target:",[26,447,449],{"className":28,"code":448,"language":30,"meta":31,"style":31},"readlink -f \u002Fsrv\u002Fmyapp\u002Fcurrent\n",[33,450,451],{"__ignoreMap":31},[36,452,453,456,459],{"class":38,"line":39},[36,454,455],{"class":62},"readlink",[36,457,458],{"class":42}," -f",[36,460,461],{"class":46}," \u002Fsrv\u002Fmyapp\u002Fcurrent\n",[158,463,464,467,469,470,472,473],{},[161,465,466],{},"Deploy the new code",[165,468],{},"Update the code in place or deploy a new release directory.",[165,471],{},"Example with Git:",[26,474,476],{"className":28,"code":475,"language":30,"meta":31,"style":31},"cd \u002Fsrv\u002Fmyapp\u002Fcurrent\ngit fetch --all\ngit checkout \u003Ctag-or-commit>\n",[33,477,478,484,495],{"__ignoreMap":31},[36,479,480,482],{"class":38,"line":39},[36,481,43],{"class":42},[36,483,461],{"class":46},[36,485,486,489,492],{"class":38,"line":50},[36,487,488],{"class":62},"git",[36,490,491],{"class":46}," fetch",[36,493,494],{"class":42}," --all\n",[36,496,497,499,502,506,509,513],{"class":38,"line":59},[36,498,488],{"class":62},[36,500,501],{"class":46}," checkout",[36,503,505],{"class":504},"szBVR"," \u003C",[36,507,508],{"class":46},"tag-or-commi",[36,510,512],{"class":511},"sVt8B","t",[36,514,515],{"class":504},">\n",[158,517,518,521,523,524],{},[161,519,520],{},"Install dependencies",[165,522],{},"Install Python package changes before the reload.",[26,525,527],{"className":28,"code":526,"language":30,"meta":31,"style":31},"source \u002Fsrv\u002Fmyapp\u002F.venv\u002Fbin\u002Factivate\npip install -r \u002Fsrv\u002Fmyapp\u002Fcurrent\u002Frequirements.txt\n",[33,528,529,536],{"__ignoreMap":31},[36,530,531,533],{"class":38,"line":39},[36,532,53],{"class":42},[36,534,535],{"class":46}," \u002Fsrv\u002Fmyapp\u002F.venv\u002Fbin\u002Factivate\n",[36,537,538,540,542,544],{"class":38,"line":50},[36,539,63],{"class":62},[36,541,66],{"class":46},[36,543,69],{"class":42},[36,545,546],{"class":46}," \u002Fsrv\u002Fmyapp\u002Fcurrent\u002Frequirements.txt\n",[158,548,549,552,554,555],{},[161,550,551],{},"Apply safe database migrations",[165,553],{},"Run migrations before the reload only if the migration is backward-compatible with the currently running code.",[26,556,558],{"className":28,"code":557,"language":30,"meta":31,"style":31},"source \u002Fsrv\u002Fmyapp\u002F.venv\u002Fbin\u002Factivate\ncd \u002Fsrv\u002Fmyapp\u002Fcurrent\nflask db upgrade\n",[33,559,560,566,572],{"__ignoreMap":31},[36,561,562,564],{"class":38,"line":39},[36,563,53],{"class":42},[36,565,535],{"class":46},[36,567,568,570],{"class":38,"line":50},[36,569,43],{"class":42},[36,571,461],{"class":46},[36,573,574,576,578],{"class":38,"line":59},[36,575,78],{"class":62},[36,577,81],{"class":46},[36,579,84],{"class":46},[158,581,582,585,587,588],{},[161,583,584],{},"Validate environment configuration",[165,586],{},"Check environment files and required variables before reloading.",[26,589,591],{"className":28,"code":590,"language":30,"meta":31,"style":31},"sudo systemctl cat myapp\nsudo grep -v '^#' \u002Fetc\u002Fmyapp.env\n",[33,592,593,604],{"__ignoreMap":31},[36,594,595,597,599,602],{"class":38,"line":39},[36,596,90],{"class":62},[36,598,93],{"class":46},[36,600,601],{"class":46}," cat",[36,603,99],{"class":46},[36,605,606,608,611,614,617],{"class":38,"line":50},[36,607,90],{"class":62},[36,609,610],{"class":46}," grep",[36,612,613],{"class":42}," -v",[36,615,616],{"class":46}," '^#'",[36,618,619],{"class":46}," \u002Fetc\u002Fmyapp.env\n",[158,621,622,625,627,628,643,645,646,648],{},[161,623,624],{},"Trigger a graceful Gunicorn reload",[165,626],{},"This is the core deployment action.",[26,629,631],{"className":28,"code":630,"language":30,"meta":31,"style":31},"sudo systemctl reload myapp\n",[33,632,633],{"__ignoreMap":31},[36,634,635,637,639,641],{"class":38,"line":39},[36,636,90],{"class":62},[36,638,93],{"class":46},[36,640,96],{"class":46},[36,642,99],{"class":46},[165,644],{},"This sends ",[33,647,141],{}," to the Gunicorn master so workers are replaced gracefully.",[158,650,651,654,656,657],{},[161,652,653],{},"Verify the service is still healthy",[165,655],{},"Check service state and logs immediately after the reload.",[26,658,660],{"className":28,"code":659,"language":30,"meta":31,"style":31},"sudo systemctl status myapp --no-pager\nsudo journalctl -u myapp -n 100 --no-pager\n",[33,661,662,674],{"__ignoreMap":31},[36,663,664,666,668,670,672],{"class":38,"line":39},[36,665,90],{"class":62},[36,667,93],{"class":46},[36,669,109],{"class":46},[36,671,112],{"class":46},[36,673,115],{"class":42},[36,675,676,678,681,684,686,689,692],{"class":38,"line":50},[36,677,90],{"class":62},[36,679,680],{"class":46}," journalctl",[36,682,683],{"class":42}," -u",[36,685,112],{"class":46},[36,687,688],{"class":42}," -n",[36,690,691],{"class":42}," 100",[36,693,115],{"class":42},[158,695,696,699,701,702,705,706,719,721],{},[161,697,698],{},"Test Gunicorn directly if using TCP",[165,700],{},"If Gunicorn binds to ",[33,703,704],{},"127.0.0.1:8000",", verify direct responses:",[26,707,709],{"className":28,"code":708,"language":30,"meta":31,"style":31},"curl -I http:\u002F\u002F127.0.0.1:8000\n",[33,710,711],{"__ignoreMap":31},[36,712,713,715,717],{"class":38,"line":39},[36,714,121],{"class":62},[36,716,124],{"class":42},[36,718,127],{"class":46},[165,720],{},"If you use a Unix socket, validate through Nginx instead.",[158,723,724,727,729,730,744,746],{},[161,725,726],{},"Test through Nginx",[165,728],{},"Confirm the public path is serving the new release.",[26,731,733],{"className":28,"code":732,"language":30,"meta":31,"style":31},"curl -I https:\u002F\u002Fyourdomain.com\n",[33,734,735],{"__ignoreMap":31},[36,736,737,739,741],{"class":38,"line":39},[36,738,121],{"class":62},[36,740,124],{"class":42},[36,742,743],{"class":46}," https:\u002F\u002Fyourdomain.com\n",[165,745],{},"Also test a dynamic route that proves the new code is active.",[158,748,749,752,754,755,371],{},[161,750,751],{},"Update static assets if the release changed them",[165,753],{},"If your release includes static file updates, sync or collect them before final validation. If static assets fail after deploy, see ",[756,757,759],"a",{"href":758},"\u002Ffix-issues\u002Fflask-static-files-not-loading-in-production","Flask Static Files Not Loading in Production",[158,761,762,765,767,768,355,770],{},[161,763,764],{},"Roll back if new workers fail to boot",[165,766],{},"Revert to the previous release target and reload again.",[165,769],{},[26,771,773],{"className":28,"code":772,"language":30,"meta":31,"style":31},"ln -sfn \u002Fsrv\u002Fmyapp\u002Freleases\u002F\u003Cprevious-release> \u002Fsrv\u002Fmyapp\u002Fcurrent\nsudo systemctl reload myapp\n",[33,774,775,800],{"__ignoreMap":31},[36,776,777,780,783,786,789,792,795,798],{"class":38,"line":39},[36,778,779],{"class":62},"ln",[36,781,782],{"class":42}," -sfn",[36,784,785],{"class":46}," \u002Fsrv\u002Fmyapp\u002Freleases\u002F",[36,787,788],{"class":504},"\u003C",[36,790,791],{"class":46},"previous-releas",[36,793,794],{"class":511},"e",[36,796,797],{"class":504},">",[36,799,461],{"class":46},[36,801,802,804,806,808],{"class":38,"line":50},[36,803,90],{"class":62},[36,805,93],{"class":46},[36,807,96],{"class":46},[36,809,99],{"class":46},[18,811,813],{"id":812},"common-causes","Common Causes",[815,816,817,832,844,850,856,862,876,882,888],"ul",{},[158,818,819,828,829,831],{},[161,820,821,822,825,826],{},"Using ",[33,823,824],{},"systemctl restart"," instead of ",[33,827,133],{}," → creates a stop\u002Fstart gap → add ",[33,830,137],{}," and use graceful reload.",[158,833,834,840,841,371],{},[161,835,836,837,839],{},"Gunicorn unit has no ",[33,838,137],{}," directive"," → systemd cannot perform a graceful reload → define ",[33,842,843],{},"ExecReload=\u002Fbin\u002Fkill -HUP $MAINPID",[158,845,846,849],{},[161,847,848],{},"Only one Gunicorn worker is running"," → no spare capacity during replacement → increase workers to at least 2.",[158,851,852,855],{},[161,853,854],{},"New code fails at import time"," → new workers never become healthy → check Gunicorn logs and fix app startup errors before reloading again.",[158,857,858,861],{},[161,859,860],{},"Database migration is not backward-compatible"," → old workers or new code break during transition → split schema and code changes across multiple releases.",[158,863,864,867,868,871,872,875],{},[161,865,866],{},"Environment variables changed but systemd did not load them correctly"," → new workers boot with missing config → verify ",[33,869,870],{},"EnvironmentFile"," and run ",[33,873,874],{},"daemon-reload"," if the unit changed.",[158,877,878,881],{},[161,879,880],{},"Socket or port changed during deploy"," → Nginx points to the wrong upstream → keep the Gunicorn bind path stable or update Nginx and validate before reload.",[158,883,884,887],{},[161,885,886],{},"Static files were updated but not collected or synced"," → app code is live but assets are stale or missing → deploy static assets before validation.",[158,889,890,893],{},[161,891,892],{},"Long-running requests delay worker turnover"," → reload appears stuck or slow → review request timeouts and long-running endpoints.",[18,895,897],{"id":896},"debugging-section","Debugging Section",[14,899,900],{},"Check the service definition, service state, worker processes, socket bindings, and proxy status.",[902,903,905],"h3",{"id":904},"commands-to-run","Commands to run",[26,907,909],{"className":28,"code":908,"language":30,"meta":31,"style":31},"sudo systemctl cat myapp\nsudo systemctl status myapp --no-pager\nsudo journalctl -u myapp -n 200 --no-pager\nsudo journalctl -u myapp -f\nps aux | grep gunicorn\nsudo ss -ltnp | grep 8000\nsudo ss -lx | grep myapp.sock\ncurl -I http:\u002F\u002F127.0.0.1:8000\ncurl -I https:\u002F\u002Fyourdomain.com\nsudo nginx -t\nsudo journalctl -u nginx -n 100 --no-pager\nreadlink -f \u002Fsrv\u002Fmyapp\u002Fcurrent\nsource \u002Fsrv\u002Fmyapp\u002F.venv\u002Fbin\u002Factivate && flask db current\nsource \u002Fsrv\u002Fmyapp\u002F.venv\u002Fbin\u002Factivate && flask db upgrade\nsudo systemctl reload myapp\n",[33,910,911,921,933,950,963,979,996,1012,1020,1028,1036,1052,1060,1077,1091],{"__ignoreMap":31},[36,912,913,915,917,919],{"class":38,"line":39},[36,914,90],{"class":62},[36,916,93],{"class":46},[36,918,601],{"class":46},[36,920,99],{"class":46},[36,922,923,925,927,929,931],{"class":38,"line":50},[36,924,90],{"class":62},[36,926,93],{"class":46},[36,928,109],{"class":46},[36,930,112],{"class":46},[36,932,115],{"class":42},[36,934,935,937,939,941,943,945,948],{"class":38,"line":59},[36,936,90],{"class":62},[36,938,680],{"class":46},[36,940,683],{"class":42},[36,942,112],{"class":46},[36,944,688],{"class":42},[36,946,947],{"class":42}," 200",[36,949,115],{"class":42},[36,951,952,954,956,958,960],{"class":38,"line":75},[36,953,90],{"class":62},[36,955,680],{"class":46},[36,957,683],{"class":42},[36,959,112],{"class":46},[36,961,962],{"class":42}," -f\n",[36,964,965,968,971,974,976],{"class":38,"line":87},[36,966,967],{"class":62},"ps",[36,969,970],{"class":46}," aux",[36,972,973],{"class":504}," |",[36,975,610],{"class":62},[36,977,978],{"class":46}," gunicorn\n",[36,980,981,983,986,989,991,993],{"class":38,"line":102},[36,982,90],{"class":62},[36,984,985],{"class":46}," ss",[36,987,988],{"class":42}," -ltnp",[36,990,973],{"class":504},[36,992,610],{"class":62},[36,994,995],{"class":42}," 8000\n",[36,997,998,1000,1002,1005,1007,1009],{"class":38,"line":118},[36,999,90],{"class":62},[36,1001,985],{"class":46},[36,1003,1004],{"class":42}," -lx",[36,1006,973],{"class":504},[36,1008,610],{"class":62},[36,1010,1011],{"class":46}," myapp.sock\n",[36,1013,1014,1016,1018],{"class":38,"line":257},[36,1015,121],{"class":62},[36,1017,124],{"class":42},[36,1019,127],{"class":46},[36,1021,1022,1024,1026],{"class":38,"line":263},[36,1023,121],{"class":62},[36,1025,124],{"class":42},[36,1027,743],{"class":46},[36,1029,1030,1032,1034],{"class":38,"line":269},[36,1031,90],{"class":62},[36,1033,191],{"class":46},[36,1035,194],{"class":42},[36,1037,1038,1040,1042,1044,1046,1048,1050],{"class":38,"line":275},[36,1039,90],{"class":62},[36,1041,680],{"class":46},[36,1043,683],{"class":42},[36,1045,191],{"class":46},[36,1047,688],{"class":42},[36,1049,691],{"class":42},[36,1051,115],{"class":42},[36,1053,1054,1056,1058],{"class":38,"line":281},[36,1055,455],{"class":62},[36,1057,458],{"class":42},[36,1059,461],{"class":46},[36,1061,1062,1064,1067,1070,1072,1074],{"class":38,"line":287},[36,1063,53],{"class":42},[36,1065,1066],{"class":46}," \u002Fsrv\u002Fmyapp\u002F.venv\u002Fbin\u002Factivate",[36,1068,1069],{"class":511}," && ",[36,1071,78],{"class":62},[36,1073,81],{"class":46},[36,1075,1076],{"class":46}," current\n",[36,1078,1079,1081,1083,1085,1087,1089],{"class":38,"line":293},[36,1080,53],{"class":42},[36,1082,1066],{"class":46},[36,1084,1069],{"class":511},[36,1086,78],{"class":62},[36,1088,81],{"class":46},[36,1090,84],{"class":46},[36,1092,1093,1095,1097,1099],{"class":38,"line":299},[36,1094,90],{"class":62},[36,1096,93],{"class":46},[36,1098,96],{"class":46},[36,1100,99],{"class":46},[902,1102,1104],{"id":1103},"what-to-look-for","What to look for",[815,1106,1107,1112,1115,1118,1124,1130,1133],{},[158,1108,1109,1111],{},[33,1110,843],{}," exists in the active unit",[158,1113,1114],{},"Gunicorn master stays running during reload",[158,1116,1117],{},"New worker PIDs appear after the reload",[158,1119,1120,1121],{},"No import errors, missing environment variables, or migration failures in ",[33,1122,1123],{},"journalctl",[158,1125,1126,1127],{},"Nginx configuration passes ",[33,1128,1129],{},"nginx -t",[158,1131,1132],{},"The app still answers through the public domain",[158,1134,1135,1136,1139],{},"No ",[33,1137,1138],{},"502 Bad Gateway"," responses appear during validation",[14,1141,1142,1143,1147,1148,1152,1153,371],{},"If requests fail during reload, see ",[756,1144,1146],{"href":1145},"\u002Ffix-issues\u002Ffix-flask-502-bad-gateway-step-by-step-guide","Fix Flask 502 Bad Gateway (Step-by-Step Guide)",". If workers do not come back with new code, see ",[756,1149,1151],{"href":1150},"\u002Ffix-issues\u002Fflask-app-not-reloading-after-deploy","Flask App Not Reloading After Deploy",". If Gunicorn fails completely, see ",[756,1154,1156],{"href":1155},"\u002Ffix-issues\u002Fflask-gunicorn-service-failed-to-start","Flask Gunicorn Service Failed to Start",[18,1158,1160],{"id":1159},"checklist","Checklist",[815,1162,1165,1177,1183,1189,1195,1201,1210,1220,1226,1232],{"className":1163},[1164],"contains-task-list",[158,1166,1169,1173,1174,1176],{"className":1167},[1168],"task-list-item",[1170,1171],"input",{"disabled":238,"type":1172},"checkbox"," Gunicorn systemd unit has ",[33,1175,137],{}," configured",[158,1178,1180,1182],{"className":1179},[1168],[1170,1181],{"disabled":238,"type":1172}," Gunicorn runs with multiple workers",[158,1184,1186,1188],{"className":1185},[1168],[1170,1187],{"disabled":238,"type":1172}," Nginx upstream target did not change during deploy",[158,1190,1192,1194],{"className":1191},[1168],[1170,1193],{"disabled":238,"type":1172}," New dependencies installed successfully",[158,1196,1198,1200],{"className":1197},[1168],[1170,1199],{"disabled":238,"type":1172}," Database migrations completed without error",[158,1202,1204,1206,1207,1209],{"className":1203},[1168],[1170,1205],{"disabled":238,"type":1172}," ",[33,1208,133],{}," returns success",[158,1211,1213,1215,1216,1219],{"className":1212},[1168],[1170,1214],{"disabled":238,"type":1172}," No ",[33,1217,1218],{},"502"," errors appear during or after reload",[158,1221,1223,1225],{"className":1222},[1168],[1170,1224],{"disabled":238,"type":1172}," New release responds through Nginx",[158,1227,1229,1231],{"className":1228},[1168],[1170,1230],{"disabled":238,"type":1172}," Logs show new workers started cleanly",[158,1233,1235,1237],{"className":1234},[1168],[1170,1236],{"disabled":238,"type":1172}," Rollback path is available if validation fails",[14,1239,1240,1241,371],{},"For broader production validation, use ",[756,1242,1244],{"href":1243},"\u002Fchecklist\u002Fflask-production-checklist-everything-you-must-do","Flask Production Checklist (Everything You Must Do)",[18,1246,1248],{"id":1247},"related-guides","Related Guides",[815,1250,1251,1257,1261,1265],{},[158,1252,1253],{},[756,1254,1256],{"href":1255},"\u002Fdeploy\u002Fdeploy-flask-with-nginx-plus-gunicorn-step-by-step-guide","Deploy Flask with Nginx + Gunicorn (Step-by-Step Guide)",[158,1258,1259],{},[756,1260,1244],{"href":1243},[158,1262,1263],{},[756,1264,1146],{"href":1145},[158,1266,1267],{},[756,1268,1151],{"href":1150},[18,1270,1272],{"id":1271},"faq","FAQ",[902,1274,1276],{"id":1275},"what-signal-should-be-used-for-a-zero-downtime-gunicorn-reload","What signal should be used for a zero-downtime Gunicorn reload?",[14,1278,130,1279,1281],{},[33,1280,141],{}," for a standard graceful reload of Gunicorn workers in most systemd-managed Flask setups.",[902,1283,1285],{"id":1284},"can-i-use-this-strategy-with-a-unix-socket","Can I use this strategy with a Unix socket?",[14,1287,1288],{},"Yes. A stable Unix socket path works well as long as Nginx continues pointing to the same socket.",[902,1290,1292],{"id":1291},"why-am-i-still-seeing-brief-502-errors-during-reload","Why am I still seeing brief 502 errors during reload?",[14,1294,1295],{},"Usually because workers fail to start, only one worker is configured, or Nginx is pointed at the wrong upstream.",[902,1297,1299],{"id":1298},"do-i-need-nginx-for-zero-downtime","Do I need Nginx for zero downtime?",[14,1301,1302],{},"It is strongly recommended. Nginx buffers and proxies requests while Gunicorn workers are replaced.",[902,1304,1306],{"id":1305},"should-i-reload-systemd-too","Should I reload systemd too?",[14,1308,1309,1310,1313,1314,1317],{},"Only run ",[33,1311,1312],{},"systemctl daemon-reload"," if you changed the unit file. Use ",[33,1315,1316],{},"systemctl reload myapp"," for the application reload itself.",[18,1319,1321],{"id":1320},"final-takeaway","Final Takeaway",[14,1323,1324],{},"Zero-downtime Flask deploys are usually a graceful Gunicorn reload problem, not an Nginx problem. Keep the bind target stable, run safe migrations, use multiple workers, and reload the Gunicorn master through systemd instead of restarting the service.",[1326,1327,1328],"style",{},"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 .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}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 .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}",{"title":31,"searchDepth":50,"depth":50,"links":1330},[1331,1332,1333,1334,1335,1339,1340,1341,1348],{"id":20,"depth":50,"text":21},{"id":145,"depth":50,"text":146},{"id":152,"depth":50,"text":153},{"id":812,"depth":50,"text":813},{"id":896,"depth":50,"text":897,"children":1336},[1337,1338],{"id":904,"depth":59,"text":905},{"id":1103,"depth":59,"text":1104},{"id":1159,"depth":50,"text":1160},{"id":1247,"depth":50,"text":1248},{"id":1271,"depth":50,"text":1272,"children":1342},[1343,1344,1345,1346,1347],{"id":1275,"depth":59,"text":1276},{"id":1284,"depth":59,"text":1285},{"id":1291,"depth":59,"text":1292},{"id":1298,"depth":59,"text":1299},{"id":1305,"depth":59,"text":1306},{"id":1320,"depth":50,"text":1321},"Complete guide on zero downtime flask deployment (gunicorn reload strategy) for Flask production environments.","md",{"ogTitle":5,"ogDescription":1349,"twitterCard":1352,"robots":1353,"canonical":1354},"summary_large_image","index, follow","https:\u002F\u002Fflask-deployment.com\u002Foptimize\u002Fzero-downtime-flask-deployment-gunicorn-reload-strategy","\u002Foptimize\u002Fzero-downtime-flask-deployment-gunicorn-reload-strategy",{"title":5,"description":1349},"optimize\u002Fzero-downtime-flask-deployment-gunicorn-reload-strategy","3l_ojUWocvgup3L665jrSLV57zzga-bgykXqNsOGEIA",1776805765059]