[{"data":1,"prerenderedAt":1535},["ShallowReactive",2],{"\u002Freference\u002Fgunicorn-vs-waitress-for-flask-production":3},{"id":4,"title":5,"body":6,"description":1525,"extension":1526,"meta":1527,"navigation":63,"path":1531,"seo":1532,"stem":1533,"__hash__":1534},"content\u002Freference\u002Fgunicorn-vs-waitress-for-flask-production.md","Gunicorn vs Waitress for Flask Production",{"type":7,"value":8,"toc":1495},"minimark",[9,13,17,22,25,86,89,131,134,161,165,168,183,187,192,195,207,211,222,229,312,315,330,333,337,340,357,360,377,380,399,403,406,425,428,444,448,451,470,472,484,488,491,494,587,590,606,609,627,635,639,644,719,722,761,765,770,833,835,870,874,877,899,902,913,917,920,951,962,966,969,993,997,1000,1017,1020,1024,1085,1089,1092,1104,1107,1125,1128,1146,1149,1161,1164,1180,1183,1218,1221,1281,1283,1295,1298,1332,1339,1343,1416,1423,1427,1445,1449,1453,1456,1460,1463,1467,1470,1474,1477,1481,1484,1488,1491],[10,11,5],"h1",{"id":12},"gunicorn-vs-waitress-for-flask-production",[14,15,16],"p",{},"If you're choosing between Gunicorn and Waitress for Flask production, this guide helps you make the decision quickly and set up the right server. It shows the default production choice, when to use each option, and how to validate that the app is serving traffic correctly.",[18,19,21],"h2",{"id":20},"quick-fix-quick-setup","Quick Fix \u002F Quick Setup",[14,23,24],{},"Use Gunicorn by default for Linux production behind Nginx:",[26,27,32],"pre",{"className":28,"code":29,"language":30,"meta":31,"style":31},"language-bash shiki shiki-themes github-light github-dark","python -m pip install gunicorn\n\ngunicorn -w 3 -b 127.0.0.1:8000 'app:app'\n","bash","",[33,34,35,58,65],"code",{"__ignoreMap":31},[36,37,40,44,48,52,55],"span",{"class":38,"line":39},"line",1,[36,41,43],{"class":42},"sScJk","python",[36,45,47],{"class":46},"sj4cs"," -m",[36,49,51],{"class":50},"sZZnC"," pip",[36,53,54],{"class":50}," install",[36,56,57],{"class":50}," gunicorn\n",[36,59,61],{"class":38,"line":60},2,[36,62,64],{"emptyLinePlaceholder":63},true,"\n",[36,66,68,71,74,77,80,83],{"class":38,"line":67},3,[36,69,70],{"class":42},"gunicorn",[36,72,73],{"class":46}," -w",[36,75,76],{"class":46}," 3",[36,78,79],{"class":46}," -b",[36,81,82],{"class":50}," 127.0.0.1:8000",[36,84,85],{"class":50}," 'app:app'\n",[14,87,88],{},"Use Waitress when you need a simpler pure-Python WSGI server or Windows support:",[26,90,92],{"className":28,"code":91,"language":30,"meta":31,"style":31},"python -m pip install waitress\n\nwaitress-serve --host 127.0.0.1 --port 8000 app:app\n",[33,93,94,107,111],{"__ignoreMap":31},[36,95,96,98,100,102,104],{"class":38,"line":39},[36,97,43],{"class":42},[36,99,47],{"class":46},[36,101,51],{"class":50},[36,103,54],{"class":50},[36,105,106],{"class":50}," waitress\n",[36,108,109],{"class":38,"line":60},[36,110,64],{"emptyLinePlaceholder":63},[36,112,113,116,119,122,125,128],{"class":38,"line":67},[36,114,115],{"class":42},"waitress-serve",[36,117,118],{"class":46}," --host",[36,120,121],{"class":46}," 127.0.0.1",[36,123,124],{"class":46}," --port",[36,126,127],{"class":46}," 8000",[36,129,130],{"class":50}," app:app\n",[14,132,133],{},"Decision shortcut:",[135,136,137,146,156],"ul",{},[138,139,140,141,145],"li",{},"Use ",[142,143,144],"strong",{},"Gunicorn"," for Linux VPS, Ubuntu, Debian, Nginx, and systemd-based deployments",[138,147,140,148,151,152,155],{},[142,149,150],{},"Waitress"," when you need ",[142,153,154],{},"Windows support"," or want a simpler pure-Python setup",[138,157,158,159],{},"In most Linux production cases, choose ",[142,160,144],{},[18,162,164],{"id":163},"whats-happening","What’s Happening",[14,166,167],{},"Flask’s built-in development server is not suitable for production traffic or service management. You need a production WSGI server to run the app reliably.",[135,169,170,175,180],{},[138,171,172,174],{},[142,173,144],{}," is the standard Linux choice for Flask behind Nginx",[138,176,177,179],{},[142,178,150],{}," is a pure-Python WSGI server that works well when cross-platform support matters",[138,181,182],{},"The right choice depends on OS, operational model, and whether you are following the standard Nginx + systemd deployment pattern",[18,184,186],{"id":185},"step-by-step-guide","Step-by-Step Guide",[188,189,191],"h3",{"id":190},"_1-choose-the-server-based-on-your-environment","1. Choose the server based on your environment",[14,193,194],{},"Use this rule set:",[135,196,197,202],{},[138,198,199,201],{},[142,200,144],{},": Linux server, Nginx reverse proxy, systemd service, standard Flask production",[138,203,204,206],{},[142,205,150],{},": Windows support required, pure-Python preference, simpler cross-platform deployment",[188,208,210],{"id":209},"_2-confirm-the-flask-app-exposes-a-wsgi-callable","2. Confirm the Flask app exposes a WSGI callable",[14,212,213,214,217,218,221],{},"Your app must expose a callable like ",[33,215,216],{},"app:app"," or ",[33,219,220],{},"wsgi:app",".",[14,223,224,225,228],{},"Example ",[33,226,227],{},"app.py",":",[26,230,233],{"className":231,"code":232,"language":43,"meta":31,"style":31},"language-python shiki shiki-themes github-light github-dark","from flask import Flask\n\napp = Flask(__name__)\n\n@app.route(\"\u002F\")\ndef index():\n    return \"OK\"\n",[33,234,235,251,255,272,277,291,303],{"__ignoreMap":31},[36,236,237,241,245,248],{"class":38,"line":39},[36,238,240],{"class":239},"szBVR","from",[36,242,244],{"class":243},"sVt8B"," flask ",[36,246,247],{"class":239},"import",[36,249,250],{"class":243}," Flask\n",[36,252,253],{"class":38,"line":60},[36,254,64],{"emptyLinePlaceholder":63},[36,256,257,260,263,266,269],{"class":38,"line":67},[36,258,259],{"class":243},"app ",[36,261,262],{"class":239},"=",[36,264,265],{"class":243}," Flask(",[36,267,268],{"class":46},"__name__",[36,270,271],{"class":243},")\n",[36,273,275],{"class":38,"line":274},4,[36,276,64],{"emptyLinePlaceholder":63},[36,278,280,283,286,289],{"class":38,"line":279},5,[36,281,282],{"class":42},"@app.route",[36,284,285],{"class":243},"(",[36,287,288],{"class":50},"\"\u002F\"",[36,290,271],{"class":243},[36,292,294,297,300],{"class":38,"line":293},6,[36,295,296],{"class":239},"def",[36,298,299],{"class":42}," index",[36,301,302],{"class":243},"():\n",[36,304,306,309],{"class":38,"line":305},7,[36,307,308],{"class":239},"    return",[36,310,311],{"class":50}," \"OK\"\n",[14,313,314],{},"Test the import path:",[26,316,318],{"className":28,"code":317,"language":30,"meta":31,"style":31},"python -c \"import app; print(app.app)\"\n",[33,319,320],{"__ignoreMap":31},[36,321,322,324,327],{"class":38,"line":39},[36,323,43],{"class":42},[36,325,326],{"class":46}," -c",[36,328,329],{"class":50}," \"import app; print(app.app)\"\n",[14,331,332],{},"If this fails, fix the module name or callable before continuing.",[188,334,336],{"id":335},"_3-install-the-selected-server-in-the-project-virtual-environment","3. Install the selected server in the project virtual environment",[14,338,339],{},"For Gunicorn:",[26,341,343],{"className":28,"code":342,"language":30,"meta":31,"style":31},"python -m pip install gunicorn\n",[33,344,345],{"__ignoreMap":31},[36,346,347,349,351,353,355],{"class":38,"line":39},[36,348,43],{"class":42},[36,350,47],{"class":46},[36,352,51],{"class":50},[36,354,54],{"class":50},[36,356,57],{"class":50},[14,358,359],{},"For Waitress:",[26,361,363],{"className":28,"code":362,"language":30,"meta":31,"style":31},"python -m pip install waitress\n",[33,364,365],{"__ignoreMap":31},[36,366,367,369,371,373,375],{"class":38,"line":39},[36,368,43],{"class":42},[36,370,47],{"class":46},[36,372,51],{"class":50},[36,374,54],{"class":50},[36,376,106],{"class":50},[14,378,379],{},"Confirm the binary resolves from the virtual environment:",[26,381,383],{"className":28,"code":382,"language":30,"meta":31,"style":31},"which gunicorn\nwhich waitress-serve\n",[33,384,385,392],{"__ignoreMap":31},[36,386,387,390],{"class":38,"line":39},[36,388,389],{"class":46},"which",[36,391,57],{"class":50},[36,393,394,396],{"class":38,"line":60},[36,395,389],{"class":46},[36,397,398],{"class":50}," waitress-serve\n",[188,400,402],{"id":401},"_4-test-gunicorn-directly","4. Test Gunicorn directly",[14,404,405],{},"Run Gunicorn on localhost:",[26,407,409],{"className":28,"code":408,"language":30,"meta":31,"style":31},"gunicorn -w 3 -b 127.0.0.1:8000 'app:app'\n",[33,410,411],{"__ignoreMap":31},[36,412,413,415,417,419,421,423],{"class":38,"line":39},[36,414,70],{"class":42},[36,416,73],{"class":46},[36,418,76],{"class":46},[36,420,79],{"class":46},[36,422,82],{"class":50},[36,424,85],{"class":50},[14,426,427],{},"Then test it:",[26,429,431],{"className":28,"code":430,"language":30,"meta":31,"style":31},"curl -I http:\u002F\u002F127.0.0.1:8000\n",[33,432,433],{"__ignoreMap":31},[36,434,435,438,441],{"class":38,"line":39},[36,436,437],{"class":42},"curl",[36,439,440],{"class":46}," -I",[36,442,443],{"class":50}," http:\u002F\u002F127.0.0.1:8000\n",[188,445,447],{"id":446},"_5-test-waitress-directly","5. Test Waitress directly",[14,449,450],{},"Run Waitress on localhost:",[26,452,454],{"className":28,"code":453,"language":30,"meta":31,"style":31},"waitress-serve --host 127.0.0.1 --port 8000 app:app\n",[33,455,456],{"__ignoreMap":31},[36,457,458,460,462,464,466,468],{"class":38,"line":39},[36,459,115],{"class":42},[36,461,118],{"class":46},[36,463,121],{"class":46},[36,465,124],{"class":46},[36,467,127],{"class":46},[36,469,130],{"class":50},[14,471,427],{},[26,473,474],{"className":28,"code":430,"language":30,"meta":31,"style":31},[33,475,476],{"__ignoreMap":31},[36,477,478,480,482],{"class":38,"line":39},[36,479,437],{"class":42},[36,481,440],{"class":46},[36,483,443],{"class":50},[188,485,487],{"id":486},"_6-put-nginx-in-front-of-the-wsgi-server","6. Put Nginx in front of the WSGI server",[14,489,490],{},"Do not expose Gunicorn or Waitress directly in a standard production setup.",[14,492,493],{},"Example Nginx server block:",[26,495,499],{"className":496,"code":497,"language":498,"meta":31,"style":31},"language-nginx shiki shiki-themes github-light github-dark","server {\n    listen 80;\n    server_name your-domain.com;\n\n    location \u002Fstatic\u002F {\n        alias \u002Fsrv\u002Fflaskapp\u002Fstatic\u002F;\n    }\n\n    location \u002F {\n        proxy_pass http:\u002F\u002F127.0.0.1:8000;\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}\n","nginx",[33,500,501,506,511,516,520,525,530,535,540,546,552,558,564,570,576,581],{"__ignoreMap":31},[36,502,503],{"class":38,"line":39},[36,504,505],{},"server {\n",[36,507,508],{"class":38,"line":60},[36,509,510],{},"    listen 80;\n",[36,512,513],{"class":38,"line":67},[36,514,515],{},"    server_name your-domain.com;\n",[36,517,518],{"class":38,"line":274},[36,519,64],{"emptyLinePlaceholder":63},[36,521,522],{"class":38,"line":279},[36,523,524],{},"    location \u002Fstatic\u002F {\n",[36,526,527],{"class":38,"line":293},[36,528,529],{},"        alias \u002Fsrv\u002Fflaskapp\u002Fstatic\u002F;\n",[36,531,532],{"class":38,"line":305},[36,533,534],{},"    }\n",[36,536,538],{"class":38,"line":537},8,[36,539,64],{"emptyLinePlaceholder":63},[36,541,543],{"class":38,"line":542},9,[36,544,545],{},"    location \u002F {\n",[36,547,549],{"class":38,"line":548},10,[36,550,551],{},"        proxy_pass http:\u002F\u002F127.0.0.1:8000;\n",[36,553,555],{"class":38,"line":554},11,[36,556,557],{},"        proxy_set_header Host $host;\n",[36,559,561],{"class":38,"line":560},12,[36,562,563],{},"        proxy_set_header X-Real-IP $remote_addr;\n",[36,565,567],{"class":38,"line":566},13,[36,568,569],{},"        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n",[36,571,573],{"class":38,"line":572},14,[36,574,575],{},"        proxy_set_header X-Forwarded-Proto $scheme;\n",[36,577,579],{"class":38,"line":578},15,[36,580,534],{},[36,582,584],{"class":38,"line":583},16,[36,585,586],{},"}\n",[14,588,589],{},"Validate Nginx config:",[26,591,593],{"className":28,"code":592,"language":30,"meta":31,"style":31},"sudo nginx -t\n",[33,594,595],{"__ignoreMap":31},[36,596,597,600,603],{"class":38,"line":39},[36,598,599],{"class":42},"sudo",[36,601,602],{"class":50}," nginx",[36,604,605],{"class":46}," -t\n",[14,607,608],{},"Reload Nginx:",[26,610,612],{"className":28,"code":611,"language":30,"meta":31,"style":31},"sudo systemctl reload nginx\n",[33,613,614],{"__ignoreMap":31},[36,615,616,618,621,624],{"class":38,"line":39},[36,617,599],{"class":42},[36,619,620],{"class":50}," systemctl",[36,622,623],{"class":50}," reload",[36,625,626],{"class":50}," nginx\n",[14,628,629,630,221],{},"If you need the full baseline deployment path, use ",[631,632,634],"a",{"href":633},"\u002Fdeploy\u002Fdeploy-flask-with-nginx-plus-gunicorn-step-by-step-guide","Deploy Flask with Nginx + Gunicorn (Step-by-Step Guide)",[188,636,638],{"id":637},"_7-create-a-systemd-service-for-gunicorn-on-linux","7. Create a systemd service for Gunicorn on Linux",[14,640,224,641,228],{},[33,642,643],{},"\u002Fetc\u002Fsystemd\u002Fsystem\u002Fgunicorn.service",[26,645,649],{"className":646,"code":647,"language":648,"meta":31,"style":31},"language-ini shiki shiki-themes github-light github-dark","[Unit]\nDescription=gunicorn flask app\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fsrv\u002Fflaskapp\nEnvironment=\"PATH=\u002Fsrv\u002Fflaskapp\u002Fvenv\u002Fbin\"\nExecStart=\u002Fsrv\u002Fflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn -w 3 -b 127.0.0.1:8000 app:app\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n","ini",[33,650,651,656,661,666,670,675,680,685,690,695,700,705,709,714],{"__ignoreMap":31},[36,652,653],{"class":38,"line":39},[36,654,655],{},"[Unit]\n",[36,657,658],{"class":38,"line":60},[36,659,660],{},"Description=gunicorn flask app\n",[36,662,663],{"class":38,"line":67},[36,664,665],{},"After=network.target\n",[36,667,668],{"class":38,"line":274},[36,669,64],{"emptyLinePlaceholder":63},[36,671,672],{"class":38,"line":279},[36,673,674],{},"[Service]\n",[36,676,677],{"class":38,"line":293},[36,678,679],{},"User=www-data\n",[36,681,682],{"class":38,"line":305},[36,683,684],{},"Group=www-data\n",[36,686,687],{"class":38,"line":537},[36,688,689],{},"WorkingDirectory=\u002Fsrv\u002Fflaskapp\n",[36,691,692],{"class":38,"line":542},[36,693,694],{},"Environment=\"PATH=\u002Fsrv\u002Fflaskapp\u002Fvenv\u002Fbin\"\n",[36,696,697],{"class":38,"line":548},[36,698,699],{},"ExecStart=\u002Fsrv\u002Fflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn -w 3 -b 127.0.0.1:8000 app:app\n",[36,701,702],{"class":38,"line":554},[36,703,704],{},"Restart=always\n",[36,706,707],{"class":38,"line":560},[36,708,64],{"emptyLinePlaceholder":63},[36,710,711],{"class":38,"line":566},[36,712,713],{},"[Install]\n",[36,715,716],{"class":38,"line":572},[36,717,718],{},"WantedBy=multi-user.target\n",[14,720,721],{},"Load and start it:",[26,723,725],{"className":28,"code":724,"language":30,"meta":31,"style":31},"sudo systemctl daemon-reload\nsudo systemctl enable --now gunicorn\nsudo systemctl status gunicorn\n",[33,726,727,736,750],{"__ignoreMap":31},[36,728,729,731,733],{"class":38,"line":39},[36,730,599],{"class":42},[36,732,620],{"class":50},[36,734,735],{"class":50}," daemon-reload\n",[36,737,738,740,742,745,748],{"class":38,"line":60},[36,739,599],{"class":42},[36,741,620],{"class":50},[36,743,744],{"class":50}," enable",[36,746,747],{"class":46}," --now",[36,749,57],{"class":50},[36,751,752,754,756,759],{"class":38,"line":67},[36,753,599],{"class":42},[36,755,620],{"class":50},[36,757,758],{"class":50}," status",[36,760,57],{"class":50},[188,762,764],{"id":763},"_8-create-a-systemd-service-for-waitress-on-linux","8. Create a systemd service for Waitress on Linux",[14,766,224,767,228],{},[33,768,769],{},"\u002Fetc\u002Fsystemd\u002Fsystem\u002Fwaitress.service",[26,771,773],{"className":646,"code":772,"language":648,"meta":31,"style":31},"[Unit]\nDescription=waitress flask app\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fsrv\u002Fflaskapp\nEnvironment=\"PATH=\u002Fsrv\u002Fflaskapp\u002Fvenv\u002Fbin\"\nExecStart=\u002Fsrv\u002Fflaskapp\u002Fvenv\u002Fbin\u002Fwaitress-serve --host 127.0.0.1 --port 8000 app:app\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n",[33,774,775,779,784,788,792,796,800,804,808,812,817,821,825,829],{"__ignoreMap":31},[36,776,777],{"class":38,"line":39},[36,778,655],{},[36,780,781],{"class":38,"line":60},[36,782,783],{},"Description=waitress flask app\n",[36,785,786],{"class":38,"line":67},[36,787,665],{},[36,789,790],{"class":38,"line":274},[36,791,64],{"emptyLinePlaceholder":63},[36,793,794],{"class":38,"line":279},[36,795,674],{},[36,797,798],{"class":38,"line":293},[36,799,679],{},[36,801,802],{"class":38,"line":305},[36,803,684],{},[36,805,806],{"class":38,"line":537},[36,807,689],{},[36,809,810],{"class":38,"line":542},[36,811,694],{},[36,813,814],{"class":38,"line":548},[36,815,816],{},"ExecStart=\u002Fsrv\u002Fflaskapp\u002Fvenv\u002Fbin\u002Fwaitress-serve --host 127.0.0.1 --port 8000 app:app\n",[36,818,819],{"class":38,"line":554},[36,820,704],{},[36,822,823],{"class":38,"line":560},[36,824,64],{"emptyLinePlaceholder":63},[36,826,827],{"class":38,"line":566},[36,828,713],{},[36,830,831],{"class":38,"line":572},[36,832,718],{},[14,834,721],{},[26,836,838],{"className":28,"code":837,"language":30,"meta":31,"style":31},"sudo systemctl daemon-reload\nsudo systemctl enable --now waitress\nsudo systemctl status waitress\n",[33,839,840,848,860],{"__ignoreMap":31},[36,841,842,844,846],{"class":38,"line":39},[36,843,599],{"class":42},[36,845,620],{"class":50},[36,847,735],{"class":50},[36,849,850,852,854,856,858],{"class":38,"line":60},[36,851,599],{"class":42},[36,853,620],{"class":50},[36,855,744],{"class":50},[36,857,747],{"class":46},[36,859,106],{"class":50},[36,861,862,864,866,868],{"class":38,"line":67},[36,863,599],{"class":42},[36,865,620],{"class":50},[36,867,758],{"class":50},[36,869,106],{"class":50},[188,871,873],{"id":872},"_9-validate-that-the-service-is-listening","9. Validate that the service is listening",[14,875,876],{},"Check the upstream bind:",[26,878,880],{"className":28,"code":879,"language":30,"meta":31,"style":31},"ss -ltnp | grep 8000\n",[33,881,882],{"__ignoreMap":31},[36,883,884,887,890,893,896],{"class":38,"line":39},[36,885,886],{"class":42},"ss",[36,888,889],{"class":46}," -ltnp",[36,891,892],{"class":239}," |",[36,894,895],{"class":42}," grep",[36,897,898],{"class":46}," 8000\n",[14,900,901],{},"Expected result:",[135,903,904,910],{},[138,905,906,907],{},"A local listener on ",[33,908,909],{},"127.0.0.1:8000",[138,911,912],{},"Nginx can connect to it successfully",[188,914,916],{"id":915},"_10-validate-end-to-end-through-nginx","10. Validate end-to-end through Nginx",[14,918,919],{},"Test local and domain paths:",[26,921,923],{"className":28,"code":922,"language":30,"meta":31,"style":31},"curl -I http:\u002F\u002F127.0.0.1:8000\ncurl -I http:\u002F\u002F127.0.0.1\ncurl -I http:\u002F\u002Fyour-domain.com\n",[33,924,925,933,942],{"__ignoreMap":31},[36,926,927,929,931],{"class":38,"line":39},[36,928,437],{"class":42},[36,930,440],{"class":46},[36,932,443],{"class":50},[36,934,935,937,939],{"class":38,"line":60},[36,936,437],{"class":42},[36,938,440],{"class":46},[36,940,941],{"class":50}," http:\u002F\u002F127.0.0.1\n",[36,943,944,946,948],{"class":38,"line":67},[36,945,437],{"class":42},[36,947,440],{"class":46},[36,949,950],{"class":50}," http:\u002F\u002Fyour-domain.com\n",[14,952,953,954,957,958,221],{},"If Nginx returns ",[33,955,956],{},"502 Bad Gateway",", use ",[631,959,961],{"href":960},"\u002Ffix-issues\u002Ffix-flask-502-bad-gateway-step-by-step-guide","Fix Flask 502 Bad Gateway (Step-by-Step Guide)",[188,963,965],{"id":964},"_11-apply-the-decision-rules","11. Apply the decision rules",[14,967,968],{},"Use these operational defaults:",[135,970,971,977,982,988],{},[138,972,973,974,976],{},"Choose ",[142,975,144],{}," for Linux production unless you have a reason not to",[138,978,973,979,981],{},[142,980,150],{}," when Windows or pure-Python simplicity is the requirement",[138,983,984,985,987],{},"Prefer ",[142,986,144],{}," for CPU-heavy or standard VPS deployments",[138,989,984,990,992],{},[142,991,150],{}," only when its platform fit is the main advantage",[188,994,996],{"id":995},"_12-record-the-deployment-choice","12. Record the deployment choice",[14,998,999],{},"Document:",[135,1001,1002,1005,1008,1011,1014],{},[138,1003,1004],{},"WSGI server selected",[138,1006,1007],{},"bind address and port",[138,1009,1010],{},"systemd service name",[138,1012,1013],{},"Flask import path",[138,1015,1016],{},"Nginx upstream target",[14,1018,1019],{},"This reduces future configuration drift.",[18,1021,1023],{"id":1022},"common-causes","Common Causes",[135,1025,1026,1032,1038,1048,1057,1067,1073,1079],{},[138,1027,1028,1031],{},[142,1029,1030],{},"Using Flask’s development server in production"," → unstable or unsupported behavior → replace it with Gunicorn or Waitress",[138,1033,1034,1037],{},[142,1035,1036],{},"Choosing Waitress on Linux when the deployment expects Gunicorn-based docs"," → setup mismatch and troubleshooting friction → use Gunicorn unless there is a clear requirement otherwise",[138,1039,1040,1047],{},[142,1041,1042,1043,217,1045],{},"Incorrect import path such as ",[33,1044,216],{},[33,1046,220],{}," → server fails to start → verify module name and callable",[138,1049,1050,1053,1054,1056],{},[142,1051,1052],{},"Binding to the wrong address or port"," → Nginx cannot reach the upstream → bind to ",[33,1055,909],{}," or the configured Unix socket",[138,1058,1059,1062,1063,1066],{},[142,1060,1061],{},"Running outside the virtual environment"," → missing dependencies at startup → point systemd ",[33,1064,1065],{},"ExecStart"," to the venv binary",[138,1068,1069,1072],{},[142,1070,1071],{},"Skipping systemd service setup"," → process stops after shell exit or reboot → create and enable a service unit",[138,1074,1075,1078],{},[142,1076,1077],{},"No reverse proxy in front of the app server"," → direct exposure, weak TLS handling, poor static file handling → place Nginx in front",[138,1080,1081,1084],{},[142,1082,1083],{},"Incorrect Gunicorn worker count"," → poor performance or memory pressure → start small and tune from observed load",[18,1086,1088],{"id":1087},"debugging-section","Debugging Section",[14,1090,1091],{},"Check app import first:",[26,1093,1094],{"className":28,"code":317,"language":30,"meta":31,"style":31},[33,1095,1096],{"__ignoreMap":31},[36,1097,1098,1100,1102],{"class":38,"line":39},[36,1099,43],{"class":42},[36,1101,326],{"class":46},[36,1103,329],{"class":50},[14,1105,1106],{},"Test Gunicorn directly:",[26,1108,1109],{"className":28,"code":408,"language":30,"meta":31,"style":31},[33,1110,1111],{"__ignoreMap":31},[36,1112,1113,1115,1117,1119,1121,1123],{"class":38,"line":39},[36,1114,70],{"class":42},[36,1116,73],{"class":46},[36,1118,76],{"class":46},[36,1120,79],{"class":46},[36,1122,82],{"class":50},[36,1124,85],{"class":50},[14,1126,1127],{},"Test Waitress directly:",[26,1129,1130],{"className":28,"code":453,"language":30,"meta":31,"style":31},[33,1131,1132],{"__ignoreMap":31},[36,1133,1134,1136,1138,1140,1142,1144],{"class":38,"line":39},[36,1135,115],{"class":42},[36,1137,118],{"class":46},[36,1139,121],{"class":46},[36,1141,124],{"class":46},[36,1143,127],{"class":46},[36,1145,130],{"class":50},[14,1147,1148],{},"Test upstream response:",[26,1150,1151],{"className":28,"code":430,"language":30,"meta":31,"style":31},[33,1152,1153],{"__ignoreMap":31},[36,1154,1155,1157,1159],{"class":38,"line":39},[36,1156,437],{"class":42},[36,1158,440],{"class":46},[36,1160,443],{"class":50},[14,1162,1163],{},"Check listening sockets:",[26,1165,1166],{"className":28,"code":879,"language":30,"meta":31,"style":31},[33,1167,1168],{"__ignoreMap":31},[36,1169,1170,1172,1174,1176,1178],{"class":38,"line":39},[36,1171,886],{"class":42},[36,1173,889],{"class":46},[36,1175,892],{"class":239},[36,1177,895],{"class":42},[36,1179,898],{"class":46},[14,1181,1182],{},"Check service status:",[26,1184,1186],{"className":28,"code":1185,"language":30,"meta":31,"style":31},"sudo systemctl status gunicorn\nsudo systemctl status waitress\nsudo systemctl status nginx\n",[33,1187,1188,1198,1208],{"__ignoreMap":31},[36,1189,1190,1192,1194,1196],{"class":38,"line":39},[36,1191,599],{"class":42},[36,1193,620],{"class":50},[36,1195,758],{"class":50},[36,1197,57],{"class":50},[36,1199,1200,1202,1204,1206],{"class":38,"line":60},[36,1201,599],{"class":42},[36,1203,620],{"class":50},[36,1205,758],{"class":50},[36,1207,106],{"class":50},[36,1209,1210,1212,1214,1216],{"class":38,"line":67},[36,1211,599],{"class":42},[36,1213,620],{"class":50},[36,1215,758],{"class":50},[36,1217,626],{"class":50},[14,1219,1220],{},"Check logs:",[26,1222,1224],{"className":28,"code":1223,"language":30,"meta":31,"style":31},"sudo journalctl -u gunicorn -n 100 --no-pager\nsudo journalctl -u waitress -n 100 --no-pager\nsudo journalctl -u nginx -n 100 --no-pager\n",[33,1225,1226,1248,1265],{"__ignoreMap":31},[36,1227,1228,1230,1233,1236,1239,1242,1245],{"class":38,"line":39},[36,1229,599],{"class":42},[36,1231,1232],{"class":50}," journalctl",[36,1234,1235],{"class":46}," -u",[36,1237,1238],{"class":50}," gunicorn",[36,1240,1241],{"class":46}," -n",[36,1243,1244],{"class":46}," 100",[36,1246,1247],{"class":46}," --no-pager\n",[36,1249,1250,1252,1254,1256,1259,1261,1263],{"class":38,"line":60},[36,1251,599],{"class":42},[36,1253,1232],{"class":50},[36,1255,1235],{"class":46},[36,1257,1258],{"class":50}," waitress",[36,1260,1241],{"class":46},[36,1262,1244],{"class":46},[36,1264,1247],{"class":46},[36,1266,1267,1269,1271,1273,1275,1277,1279],{"class":38,"line":67},[36,1268,599],{"class":42},[36,1270,1232],{"class":50},[36,1272,1235],{"class":46},[36,1274,602],{"class":50},[36,1276,1241],{"class":46},[36,1278,1244],{"class":46},[36,1280,1247],{"class":46},[14,1282,589],{},[26,1284,1285],{"className":28,"code":592,"language":30,"meta":31,"style":31},[33,1286,1287],{"__ignoreMap":31},[36,1288,1289,1291,1293],{"class":38,"line":39},[36,1290,599],{"class":42},[36,1292,602],{"class":50},[36,1294,605],{"class":46},[14,1296,1297],{},"What to look for:",[135,1299,1300,1306,1312,1318,1323,1329],{},[138,1301,1302,1303],{},"import errors like ",[33,1304,1305],{},"ModuleNotFoundError",[138,1307,1308,1309],{},"bind failures such as ",[33,1310,1311],{},"Address already in use",[138,1313,1314,1315],{},"permission issues in ",[33,1316,1317],{},"WorkingDirectory",[138,1319,1320,1321],{},"wrong virtual environment path in ",[33,1322,1065],{},[138,1324,1325,1326],{},"Nginx upstream failures or ",[33,1327,1328],{},"connect() failed",[138,1330,1331],{},"mismatch between Nginx upstream port and WSGI server bind port",[14,1333,1334,1335,221],{},"If static assets fail after deployment, use ",[631,1336,1338],{"href":1337},"\u002Ffix-issues\u002Fflask-static-files-not-loading-in-production","Flask Static Files Not Loading in Production",[18,1340,1342],{"id":1341},"checklist","Checklist",[135,1344,1347,1358,1364,1373,1379,1385,1394,1404,1410],{"className":1345},[1346],"contains-task-list",[138,1348,1351,1355,1356],{"className":1349},[1350],"task-list-item",[1352,1353],"input",{"disabled":63,"type":1354},"checkbox"," Flask app exposes a valid WSGI callable such as ",[33,1357,216],{},[138,1359,1361,1363],{"className":1360},[1350],[1352,1362],{"disabled":63,"type":1354}," Chosen server is installed inside the correct virtual environment",[138,1365,1367,1369,1370,1372],{"className":1366},[1350],[1352,1368],{"disabled":63,"type":1354}," WSGI server binds to ",[33,1371,909],{}," or a Unix socket",[138,1374,1376,1378],{"className":1375},[1350],[1352,1377],{"disabled":63,"type":1354}," Nginx proxies requests to the correct upstream",[138,1380,1382,1384],{"className":1381},[1350],[1352,1383],{"disabled":63,"type":1354}," systemd service starts successfully and restarts on failure",[138,1386,1388,1390,1391,1393],{"className":1387},[1350],[1352,1389],{"disabled":63,"type":1354}," ",[33,1392,437],{}," to the local upstream returns a valid response",[138,1395,1397,1399,1400,1403],{"className":1396},[1350],[1352,1398],{"disabled":63,"type":1354}," Domain traffic works through Nginx without ",[33,1401,1402],{},"502"," errors",[138,1405,1407,1409],{"className":1406},[1350],[1352,1408],{"disabled":63,"type":1354}," Static files are served correctly",[138,1411,1413,1415],{"className":1412},[1350],[1352,1414],{"disabled":63,"type":1354}," Deployment choice is documented for future maintenance",[14,1417,1418,1419,221],{},"Use the full validation list in ",[631,1420,1422],{"href":1421},"\u002Fchecklist\u002Fflask-production-checklist-everything-you-must-do","Flask Production Checklist (Everything You Must Do)",[18,1424,1426],{"id":1425},"related-guides","Related Guides",[135,1428,1429,1433,1437,1441],{},[138,1430,1431],{},[631,1432,634],{"href":633},[138,1434,1435],{},[631,1436,961],{"href":960},[138,1438,1439],{},[631,1440,1422],{"href":1421},[138,1442,1443],{},[631,1444,1338],{"href":1337},[18,1446,1448],{"id":1447},"faq","FAQ",[188,1450,1452],{"id":1451},"which-is-better-for-flask-production-on-ubuntu","Which is better for Flask production on Ubuntu?",[14,1454,1455],{},"Gunicorn is the default choice for Ubuntu and other Linux servers, especially behind Nginx.",[188,1457,1459],{"id":1458},"when-should-i-choose-waitress","When should I choose Waitress?",[14,1461,1462],{},"Choose Waitress when you need Windows support or want a simpler pure-Python WSGI server.",[188,1464,1466],{"id":1465},"can-both-work-behind-nginx","Can both work behind Nginx?",[14,1468,1469],{},"Yes. Nginx can proxy to either Gunicorn or Waitress.",[188,1471,1473],{"id":1472},"do-i-need-systemd-with-both","Do I need systemd with both?",[14,1475,1476],{},"For stable production services on Linux, yes. Use systemd to start, restart, and manage the process.",[188,1478,1480],{"id":1479},"will-switching-from-waitress-to-gunicorn-change-my-flask-app-code","Will switching from Waitress to Gunicorn change my Flask app code?",[14,1482,1483],{},"Usually no. The main change is the server command and service configuration, not the Flask application itself.",[18,1485,1487],{"id":1486},"final-takeaway","Final Takeaway",[14,1489,1490],{},"For most Flask production deployments on Linux, choose Gunicorn behind Nginx. Choose Waitress only when cross-platform simplicity or Windows support is the main requirement. Validate the setup by confirming the app imports correctly, the service listens locally, and Nginx serves traffic end-to-end.",[1492,1493,1494],"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 .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":60,"depth":60,"links":1496},[1497,1498,1499,1513,1514,1515,1516,1517,1524],{"id":20,"depth":60,"text":21},{"id":163,"depth":60,"text":164},{"id":185,"depth":60,"text":186,"children":1500},[1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512],{"id":190,"depth":67,"text":191},{"id":209,"depth":67,"text":210},{"id":335,"depth":67,"text":336},{"id":401,"depth":67,"text":402},{"id":446,"depth":67,"text":447},{"id":486,"depth":67,"text":487},{"id":637,"depth":67,"text":638},{"id":763,"depth":67,"text":764},{"id":872,"depth":67,"text":873},{"id":915,"depth":67,"text":916},{"id":964,"depth":67,"text":965},{"id":995,"depth":67,"text":996},{"id":1022,"depth":60,"text":1023},{"id":1087,"depth":60,"text":1088},{"id":1341,"depth":60,"text":1342},{"id":1425,"depth":60,"text":1426},{"id":1447,"depth":60,"text":1448,"children":1518},[1519,1520,1521,1522,1523],{"id":1451,"depth":67,"text":1452},{"id":1458,"depth":67,"text":1459},{"id":1465,"depth":67,"text":1466},{"id":1472,"depth":67,"text":1473},{"id":1479,"depth":67,"text":1480},{"id":1486,"depth":60,"text":1487},"Complete guide on gunicorn vs waitress for flask production for Flask production environments.","md",{"ogTitle":5,"ogDescription":1525,"twitterCard":1528,"robots":1529,"canonical":1530},"summary_large_image","index, follow","https:\u002F\u002Fflask-deployment.com\u002Freference\u002Fgunicorn-vs-waitress-for-flask-production","\u002Freference\u002Fgunicorn-vs-waitress-for-flask-production",{"title":5,"description":1525},"reference\u002Fgunicorn-vs-waitress-for-flask-production","5ahpBhY6-UobfApkdZTS36B6t4fdAsFIOuYYYKsjuCY",1776805765079]