[{"data":1,"prerenderedAt":1508},["ShallowReactive",2],{"\u002Foptimize\u002Fflask-gunicorn-performance-tuning-guide":3},{"id":4,"title":5,"body":6,"description":1498,"extension":1499,"meta":1500,"navigation":1301,"path":1504,"seo":1505,"stem":1506,"__hash__":1507},"content\u002Foptimize\u002Fflask-gunicorn-performance-tuning-guide.md","Flask Gunicorn Performance Tuning Guide",{"type":7,"value":8,"toc":1487},"minimark",[9,13,17,22,25,170,181,238,249,253,256,260,721,724,748,750,771,774,791,798,809,816,819,833,836,844,857,865,873,877,957,961,964,1000,1003,1020,1023,1100,1102,1116,1119,1153,1156,1159,1195,1197,1217,1220,1246,1249,1252,1283,1286,1290,1370,1374,1398,1402,1415,1429,1445,1453,1464,1476,1480,1483],[10,11,5],"h1",{"id":12},"flask-gunicorn-performance-tuning-guide",[14,15,16],"p",{},"If you're trying to improve Flask performance in production or stabilize Gunicorn under load, this guide shows you how to tune Gunicorn step-by-step. The goal is to set safe defaults, match worker settings to your app profile, and validate performance with logs and runtime checks.",[18,19,21],"h2",{"id":20},"quick-fix-quick-setup","Quick Fix \u002F Quick Setup",[14,23,24],{},"Use this as a safe baseline for a small to medium Flask app 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","gunicorn wsgi:app \\\n  --bind 127.0.0.1:8000 \\\n  --workers 3 \\\n  --worker-class gthread \\\n  --threads 4 \\\n  --timeout 30 \\\n  --graceful-timeout 30 \\\n  --keep-alive 2 \\\n  --max-requests 1000 \\\n  --max-requests-jitter 100 \\\n  --access-logfile - \\\n  --error-logfile -\n","bash","",[33,34,35,52,63,74,85,96,107,117,128,139,150,161],"code",{"__ignoreMap":31},[36,37,40,44,48],"span",{"class":38,"line":39},"line",1,[36,41,43],{"class":42},"sScJk","gunicorn",[36,45,47],{"class":46},"sZZnC"," wsgi:app",[36,49,51],{"class":50},"sj4cs"," \\\n",[36,53,55,58,61],{"class":38,"line":54},2,[36,56,57],{"class":50},"  --bind",[36,59,60],{"class":46}," 127.0.0.1:8000",[36,62,51],{"class":50},[36,64,66,69,72],{"class":38,"line":65},3,[36,67,68],{"class":50},"  --workers",[36,70,71],{"class":50}," 3",[36,73,51],{"class":50},[36,75,77,80,83],{"class":38,"line":76},4,[36,78,79],{"class":50},"  --worker-class",[36,81,82],{"class":46}," gthread",[36,84,51],{"class":50},[36,86,88,91,94],{"class":38,"line":87},5,[36,89,90],{"class":50},"  --threads",[36,92,93],{"class":50}," 4",[36,95,51],{"class":50},[36,97,99,102,105],{"class":38,"line":98},6,[36,100,101],{"class":50},"  --timeout",[36,103,104],{"class":50}," 30",[36,106,51],{"class":50},[36,108,110,113,115],{"class":38,"line":109},7,[36,111,112],{"class":50},"  --graceful-timeout",[36,114,104],{"class":50},[36,116,51],{"class":50},[36,118,120,123,126],{"class":38,"line":119},8,[36,121,122],{"class":50},"  --keep-alive",[36,124,125],{"class":50}," 2",[36,127,51],{"class":50},[36,129,131,134,137],{"class":38,"line":130},9,[36,132,133],{"class":50},"  --max-requests",[36,135,136],{"class":50}," 1000",[36,138,51],{"class":50},[36,140,142,145,148],{"class":38,"line":141},10,[36,143,144],{"class":50},"  --max-requests-jitter",[36,146,147],{"class":50}," 100",[36,149,51],{"class":50},[36,151,153,156,159],{"class":38,"line":152},11,[36,154,155],{"class":50},"  --access-logfile",[36,157,158],{"class":46}," -",[36,160,51],{"class":50},[36,162,164,167],{"class":38,"line":163},12,[36,165,166],{"class":50},"  --error-logfile",[36,168,169],{"class":46}," -\n",[14,171,172,173,176,177,180],{},"Example ",[33,174,175],{},"systemd"," ",[33,178,179],{},"ExecStart",":",[26,182,186],{"className":183,"code":184,"language":185,"meta":31,"style":31},"language-ini shiki shiki-themes github-light github-dark","ExecStart=\u002Fpath\u002Fvenv\u002Fbin\u002Fgunicorn wsgi:app \\\n  --bind unix:\u002Frun\u002Fgunicorn.sock \\\n  --workers 3 \\\n  --worker-class gthread \\\n  --threads 4 \\\n  --timeout 30 \\\n  --graceful-timeout 30 \\\n  --keep-alive 2 \\\n  --max-requests 1000 \\\n  --max-requests-jitter 100\n","ini",[33,187,188,193,198,203,208,213,218,223,228,233],{"__ignoreMap":31},[36,189,190],{"class":38,"line":39},[36,191,192],{},"ExecStart=\u002Fpath\u002Fvenv\u002Fbin\u002Fgunicorn wsgi:app \\\n",[36,194,195],{"class":38,"line":54},[36,196,197],{},"  --bind unix:\u002Frun\u002Fgunicorn.sock \\\n",[36,199,200],{"class":38,"line":65},[36,201,202],{},"  --workers 3 \\\n",[36,204,205],{"class":38,"line":76},[36,206,207],{},"  --worker-class gthread \\\n",[36,209,210],{"class":38,"line":87},[36,211,212],{},"  --threads 4 \\\n",[36,214,215],{"class":38,"line":98},[36,216,217],{},"  --timeout 30 \\\n",[36,219,220],{"class":38,"line":109},[36,221,222],{},"  --graceful-timeout 30 \\\n",[36,224,225],{"class":38,"line":119},[36,226,227],{},"  --keep-alive 2 \\\n",[36,229,230],{"class":38,"line":130},[36,231,232],{},"  --max-requests 1000 \\\n",[36,234,235],{"class":38,"line":141},[36,236,237],{},"  --max-requests-jitter 100\n",[14,239,240,241,244,245,248],{},"Use this baseline first, then increase workers gradually. Prefer ",[33,242,243],{},"gthread"," for apps that wait on database or external I\u002FO. For CPU-heavy workloads, test ",[33,246,247],{},"sync"," workers first.",[18,250,252],{"id":251},"whats-happening","What’s Happening",[14,254,255],{},"Gunicorn performance depends on worker model, worker count, threads, timeouts, and process recycling. Too little concurrency causes request queueing and higher latency. Too much concurrency causes CPU contention, memory pressure, and unstable behavior. Reliable tuning is a balance between throughput, latency, and resource usage.",[18,257,259],{"id":258},"step-by-step-guide","Step-by-Step Guide",[261,262,263,297,316,343,396,430,456,492,618,716],"ol",{},[264,265,266,270,273,274],"li",{},[267,268,269],"strong",{},"Measure the server before changing settings.",[271,272],"br",{},"Check CPU cores, memory, and current load:",[26,275,277],{"className":28,"code":276,"language":30,"meta":31,"style":31},"nproc\nfree -m\nuptime\n",[33,278,279,284,292],{"__ignoreMap":31},[36,280,281],{"class":38,"line":39},[36,282,283],{"class":42},"nproc\n",[36,285,286,289],{"class":38,"line":54},[36,287,288],{"class":42},"free",[36,290,291],{"class":50}," -m\n",[36,293,294],{"class":38,"line":65},[36,295,296],{"class":42},"uptime\n",[264,298,299,302],{},[267,300,301],{},"Identify whether the app is CPU-bound or I\u002FO-bound.",[303,304,305,311],"ul",{},[264,306,307,308,310],{},"Use ",[33,309,247],{}," if requests spend most of their time executing Python code or heavy computation.",[264,312,307,313,315],{},[33,314,243],{}," if requests often wait on PostgreSQL, external APIs, storage, or other I\u002FO.",[264,317,318,321,323,324,327,328,331,332,340,342],{},[267,319,320],{},"Start with a conservative worker count.",[271,322],{},"For a small VPS, begin with ",[33,325,326],{},"2"," to ",[33,329,330],{},"4"," workers. For a larger host, test this baseline formula:",[26,333,338],{"className":334,"code":336,"language":337,"meta":31},[335],"language-text","workers = (2 x CPU cores) + 1\n","text",[33,339,336],{"__ignoreMap":31},[271,341],{},"This is only a starting point. Final values must be validated under load.",[264,344,345,348,350,351,387,389,390,327,392,395],{},[267,346,347],{},"Add threads only for I\u002FO-bound apps.",[271,349],{},"Example baseline:",[26,352,354],{"className":28,"code":353,"language":30,"meta":31,"style":31},"gunicorn wsgi:app \\\n  --worker-class gthread \\\n  --workers 3 \\\n  --threads 4\n",[33,355,356,364,372,380],{"__ignoreMap":31},[36,357,358,360,362],{"class":38,"line":39},[36,359,43],{"class":42},[36,361,47],{"class":46},[36,363,51],{"class":50},[36,365,366,368,370],{"class":38,"line":54},[36,367,79],{"class":50},[36,369,82],{"class":46},[36,371,51],{"class":50},[36,373,374,376,378],{"class":38,"line":65},[36,375,68],{"class":50},[36,377,71],{"class":50},[36,379,51],{"class":50},[36,381,382,384],{"class":38,"line":76},[36,383,90],{"class":50},[36,385,386],{"class":50}," 4\n",[271,388],{},"Keep thread counts modest, usually ",[33,391,326],{},[33,393,394],{},"8",".",[264,397,398,401,403,404,427,429],{},[267,399,400],{},"Set conservative timeouts.",[271,402],{},"Start with:",[26,405,407],{"className":28,"code":406,"language":30,"meta":31,"style":31},"--timeout 30 --graceful-timeout 30 --keep-alive 2\n",[33,408,409],{"__ignoreMap":31},[36,410,411,414,416,419,421,424],{"class":38,"line":39},[36,412,413],{"class":42},"--timeout",[36,415,104],{"class":50},[36,417,418],{"class":50}," --graceful-timeout",[36,420,104],{"class":50},[36,422,423],{"class":50}," --keep-alive",[36,425,426],{"class":50}," 2\n",[271,428],{},"Do not raise timeouts to hide slow application code unless the request is valid and cannot be moved out of the request path.",[264,431,432,435,437,438],{},[267,433,434],{},"Enable worker recycling.",[271,436],{},"This helps reduce long-running memory growth and stale worker processes:",[26,439,441],{"className":28,"code":440,"language":30,"meta":31,"style":31},"--max-requests 1000 --max-requests-jitter 100\n",[33,442,443],{"__ignoreMap":31},[36,444,445,448,450,453],{"class":38,"line":39},[36,446,447],{"class":42},"--max-requests",[36,449,136],{"class":50},[36,451,452],{"class":50}," --max-requests-jitter",[36,454,455],{"class":50}," 100\n",[264,457,458,461,463,464,477,479,480],{},[267,459,460],{},"Bind Gunicorn privately and let Nginx handle public traffic.",[271,462],{},"Use either a localhost port or Unix socket:",[26,465,467],{"className":28,"code":466,"language":30,"meta":31,"style":31},"--bind 127.0.0.1:8000\n",[33,468,469],{"__ignoreMap":31},[36,470,471,474],{"class":38,"line":39},[36,472,473],{"class":42},"--bind",[36,475,476],{"class":46}," 127.0.0.1:8000\n",[271,478],{},"or",[26,481,483],{"className":28,"code":482,"language":30,"meta":31,"style":31},"--bind unix:\u002Frun\u002Fgunicorn.sock\n",[33,484,485],{"__ignoreMap":31},[36,486,487,489],{"class":38,"line":39},[36,488,473],{"class":42},[36,490,491],{"class":46}," unix:\u002Frun\u002Fgunicorn.sock\n",[264,493,494,497,499,500,180,503],{},[267,495,496],{},"Move flags into a Gunicorn config file.",[271,498],{},"Create ",[33,501,502],{},"gunicorn.conf.py",[26,504,508],{"className":505,"code":506,"language":507,"meta":31,"style":31},"language-python shiki shiki-themes github-light github-dark","bind = \"unix:\u002Frun\u002Fgunicorn.sock\"\nworkers = 3\nworker_class = \"gthread\"\nthreads = 4\ntimeout = 30\ngraceful_timeout = 30\nkeepalive = 2\nmax_requests = 1000\nmax_requests_jitter = 100\naccesslog = \"-\"\nerrorlog = \"-\"\n","python",[33,509,510,523,533,543,552,562,571,580,590,599,609],{"__ignoreMap":31},[36,511,512,516,520],{"class":38,"line":39},[36,513,515],{"class":514},"sVt8B","bind ",[36,517,519],{"class":518},"szBVR","=",[36,521,522],{"class":46}," \"unix:\u002Frun\u002Fgunicorn.sock\"\n",[36,524,525,528,530],{"class":38,"line":54},[36,526,527],{"class":514},"workers ",[36,529,519],{"class":518},[36,531,532],{"class":50}," 3\n",[36,534,535,538,540],{"class":38,"line":65},[36,536,537],{"class":514},"worker_class ",[36,539,519],{"class":518},[36,541,542],{"class":46}," \"gthread\"\n",[36,544,545,548,550],{"class":38,"line":76},[36,546,547],{"class":514},"threads ",[36,549,519],{"class":518},[36,551,386],{"class":50},[36,553,554,557,559],{"class":38,"line":87},[36,555,556],{"class":514},"timeout ",[36,558,519],{"class":518},[36,560,561],{"class":50}," 30\n",[36,563,564,567,569],{"class":38,"line":98},[36,565,566],{"class":514},"graceful_timeout ",[36,568,519],{"class":518},[36,570,561],{"class":50},[36,572,573,576,578],{"class":38,"line":109},[36,574,575],{"class":514},"keepalive ",[36,577,519],{"class":518},[36,579,426],{"class":50},[36,581,582,585,587],{"class":38,"line":119},[36,583,584],{"class":514},"max_requests ",[36,586,519],{"class":518},[36,588,589],{"class":50}," 1000\n",[36,591,592,595,597],{"class":38,"line":130},[36,593,594],{"class":514},"max_requests_jitter ",[36,596,519],{"class":518},[36,598,455],{"class":50},[36,600,601,604,606],{"class":38,"line":141},[36,602,603],{"class":514},"accesslog ",[36,605,519],{"class":518},[36,607,608],{"class":46}," \"-\"\n",[36,610,611,614,616],{"class":38,"line":152},[36,612,613],{"class":514},"errorlog ",[36,615,519],{"class":518},[36,617,608],{"class":46},[264,619,620,626,628,629,674,676,677],{},[267,621,622,623,625],{},"Update ",[33,624,175],{}," to use the config file.",[271,627],{},"Example unit fragment:",[26,630,632],{"className":183,"code":631,"language":185,"meta":31,"style":31},"[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fpath\u002Fapp\nEnvironment=\"PATH=\u002Fpath\u002Fvenv\u002Fbin\"\nExecStart=\u002Fpath\u002Fvenv\u002Fbin\u002Fgunicorn -c \u002Fpath\u002Fapp\u002Fgunicorn.conf.py wsgi:app\nRestart=always\nRestartSec=5\n",[33,633,634,639,644,649,654,659,664,669],{"__ignoreMap":31},[36,635,636],{"class":38,"line":39},[36,637,638],{},"[Service]\n",[36,640,641],{"class":38,"line":54},[36,642,643],{},"User=www-data\n",[36,645,646],{"class":38,"line":65},[36,647,648],{},"Group=www-data\n",[36,650,651],{"class":38,"line":76},[36,652,653],{},"WorkingDirectory=\u002Fpath\u002Fapp\n",[36,655,656],{"class":38,"line":87},[36,657,658],{},"Environment=\"PATH=\u002Fpath\u002Fvenv\u002Fbin\"\n",[36,660,661],{"class":38,"line":98},[36,662,663],{},"ExecStart=\u002Fpath\u002Fvenv\u002Fbin\u002Fgunicorn -c \u002Fpath\u002Fapp\u002Fgunicorn.conf.py wsgi:app\n",[36,665,666],{"class":38,"line":109},[36,667,668],{},"Restart=always\n",[36,670,671],{"class":38,"line":119},[36,672,673],{},"RestartSec=5\n",[271,675],{},"Reload and restart:",[26,678,680],{"className":28,"code":679,"language":30,"meta":31,"style":31},"sudo systemctl daemon-reload\nsudo systemctl restart gunicorn\nsudo systemctl status gunicorn\n",[33,681,682,693,705],{"__ignoreMap":31},[36,683,684,687,690],{"class":38,"line":39},[36,685,686],{"class":42},"sudo",[36,688,689],{"class":46}," systemctl",[36,691,692],{"class":46}," daemon-reload\n",[36,694,695,697,699,702],{"class":38,"line":54},[36,696,686],{"class":42},[36,698,689],{"class":46},[36,700,701],{"class":46}," restart",[36,703,704],{"class":46}," gunicorn\n",[36,706,707,709,711,714],{"class":38,"line":65},[36,708,686],{"class":42},[36,710,689],{"class":46},[36,712,713],{"class":46}," status",[36,715,704],{"class":46},[264,717,718],{},[267,719,720],{},"Load test after each change.",[14,722,723],{},"Test one change at a time:",[26,725,727],{"className":28,"code":726,"language":30,"meta":31,"style":31},"hey -n 1000 -c 20 https:\u002F\u002Fyour-domain\u002F\n",[33,728,729],{"__ignoreMap":31},[36,730,731,734,737,739,742,745],{"class":38,"line":39},[36,732,733],{"class":42},"hey",[36,735,736],{"class":50}," -n",[36,738,136],{"class":50},[36,740,741],{"class":50}," -c",[36,743,744],{"class":50}," 20",[36,746,747],{"class":46}," https:\u002F\u002Fyour-domain\u002F\n",[14,749,479],{},[26,751,753],{"className":28,"code":752,"language":30,"meta":31,"style":31},"wrk -t2 -c20 -d30s https:\u002F\u002Fyour-domain\u002F\n",[33,754,755],{"__ignoreMap":31},[36,756,757,760,763,766,769],{"class":38,"line":39},[36,758,759],{"class":42},"wrk",[36,761,762],{"class":50}," -t2",[36,764,765],{"class":50}," -c20",[36,767,768],{"class":50}," -d30s",[36,770,747],{"class":46},[14,772,773],{},"Compare:",[303,775,776,779,782,785,788],{},[264,777,778],{},"average latency",[264,780,781],{},"p95\u002Fp99 latency",[264,783,784],{},"error rate",[264,786,787],{},"CPU usage",[264,789,790],{},"memory usage",[261,792,793],{"start":152},[264,794,795],{},[267,796,797],{},"Watch for signs of over-tuning.",[303,799,800,803,806],{},[264,801,802],{},"If CPU is saturated continuously, reduce workers or threads.",[264,804,805],{},"If latency is high but CPU stays low, increase concurrency carefully.",[264,807,808],{},"If memory grows until the kernel kills processes, reduce concurrency and review recycling.",[261,810,811],{"start":163},[264,812,813],{},[267,814,815],{},"Move slow work out of request handling.",[14,817,818],{},"Do not solve long-running requests by only increasing timeouts. Move tasks like:",[303,820,821,824,827,830],{},[264,822,823],{},"email sending",[264,825,826],{},"report generation",[264,828,829],{},"file processing",[264,831,832],{},"multi-API fan-out",[14,834,835],{},"into a background job system.",[261,837,839],{"start":838},13,[264,840,841],{},[267,842,843],{},"Validate Nginx and Gunicorn together.",[14,845,846,847,852,853,395],{},"Check that Nginx upstream settings, socket path, and timeout values do not override or hide Gunicorn tuning issues. If needed, review ",[848,849,851],"a",{"href":850},"\u002Foptimize\u002Fflask-nginx-performance-tuning-guide","Flask Nginx Performance Tuning Guide"," and ",[848,854,856],{"href":855},"\u002Ffix-issues\u002Ffix-flask-502-bad-gateway-step-by-step-guide","Fix Flask 502 Bad Gateway (Step-by-Step Guide)",[261,858,860],{"start":859},14,[264,861,862],{},[267,863,864],{},"Keep a known-good rollback profile.",[14,866,867,868,852,870,872],{},"Save the previous working ",[33,869,502],{},[33,871,175],{}," unit values before each tuning round.",[18,874,876],{"id":875},"common-causes","Common Causes",[303,878,879,885,891,903,909,915,921,933,939,945,951],{},[264,880,881,884],{},[267,882,883],{},"Too many workers"," → excessive context switching, high memory use, CPU thrash → reduce worker count and retest.",[264,886,887,890],{},[267,888,889],{},"Too few workers"," → requests queue during spikes, high latency with low CPU utilization → increase workers or threads gradually.",[264,892,893,896,897,899,900,902],{},[267,894,895],{},"Wrong worker class"," → poor performance for the workload pattern → use ",[33,898,247],{}," for CPU-heavy handling and ",[33,901,243],{}," for moderate I\u002FO-bound traffic.",[264,904,905,908],{},[267,906,907],{},"Too many threads per worker"," → increased contention or memory use with little gain → lower thread count and test again.",[264,910,911,914],{},[267,912,913],{},"Timeout too low"," → workers killed during valid slow requests → optimize the request path or increase timeout only when justified.",[264,916,917,920],{},[267,918,919],{},"Timeout too high"," → stuck requests consume capacity too long → reduce timeout and move long work to background jobs.",[264,922,923,926,927,852,930,395],{},[267,924,925],{},"No worker recycling"," → memory growth over time from leaks or fragmentation → add ",[33,928,929],{},"max-requests",[33,931,932],{},"max-requests-jitter",[264,934,935,938],{},[267,936,937],{},"Nginx timeout mismatch"," → Gunicorn appears slow or broken when the proxy is the actual limit → align proxy and upstream settings.",[264,940,941,944],{},[267,942,943],{},"Database pool too small"," → workers block waiting for DB connections → tune SQLAlchemy or database pool settings.",[264,946,947,950],{},[267,948,949],{},"Small VPS RAM limits"," → OOM kills or swap thrashing after concurrency increases → reduce workers and threads, then retest.",[264,952,953,956],{},[267,954,955],{},"Application code is the bottleneck"," → Gunicorn tuning has little effect → profile database queries, external calls, rendering, and caching.",[18,958,960],{"id":959},"debugging-section","Debugging Section",[14,962,963],{},"Check service state and logs:",[26,965,967],{"className":28,"code":966,"language":30,"meta":31,"style":31},"sudo systemctl status gunicorn\nsudo journalctl -u gunicorn -n 200 --no-pager\n",[33,968,969,979],{"__ignoreMap":31},[36,970,971,973,975,977],{"class":38,"line":39},[36,972,686],{"class":42},[36,974,689],{"class":46},[36,976,713],{"class":46},[36,978,704],{"class":46},[36,980,981,983,986,989,992,994,997],{"class":38,"line":54},[36,982,686],{"class":42},[36,984,985],{"class":46}," journalctl",[36,987,988],{"class":50}," -u",[36,990,991],{"class":46}," gunicorn",[36,993,736],{"class":50},[36,995,996],{"class":50}," 200",[36,998,999],{"class":50}," --no-pager\n",[14,1001,1002],{},"Look for:",[303,1004,1005,1008,1011,1014,1017],{},[264,1006,1007],{},"worker timeouts",[264,1009,1010],{},"boot failures",[264,1012,1013],{},"repeated restarts",[264,1015,1016],{},"import errors",[264,1018,1019],{},"signal exits",[14,1021,1022],{},"Check Gunicorn processes, CPU, and memory:",[26,1024,1026],{"className":28,"code":1025,"language":30,"meta":31,"style":31},"ps -o pid,ppid,%cpu,%mem,rss,cmd -C gunicorn\nps -eLf | grep gunicorn | grep -v grep\ntop -H -p $(pgrep -d',' -f gunicorn)\n",[33,1027,1028,1044,1069],{"__ignoreMap":31},[36,1029,1030,1033,1036,1039,1042],{"class":38,"line":39},[36,1031,1032],{"class":42},"ps",[36,1034,1035],{"class":50}," -o",[36,1037,1038],{"class":46}," pid,ppid,%cpu,%mem,rss,cmd",[36,1040,1041],{"class":50}," -C",[36,1043,704],{"class":46},[36,1045,1046,1048,1051,1054,1057,1059,1061,1063,1066],{"class":38,"line":54},[36,1047,1032],{"class":42},[36,1049,1050],{"class":50}," -eLf",[36,1052,1053],{"class":518}," |",[36,1055,1056],{"class":42}," grep",[36,1058,991],{"class":46},[36,1060,1053],{"class":518},[36,1062,1056],{"class":42},[36,1064,1065],{"class":50}," -v",[36,1067,1068],{"class":46}," grep\n",[36,1070,1071,1074,1077,1080,1083,1086,1089,1092,1095,1097],{"class":38,"line":65},[36,1072,1073],{"class":42},"top",[36,1075,1076],{"class":50}," -H",[36,1078,1079],{"class":50}," -p",[36,1081,1082],{"class":514}," $(",[36,1084,1085],{"class":42},"pgrep",[36,1087,1088],{"class":50}," -d",[36,1090,1091],{"class":46},"','",[36,1093,1094],{"class":50}," -f",[36,1096,991],{"class":46},[36,1098,1099],{"class":514},")\n",[14,1101,1002],{},[303,1103,1104,1107,1110,1113],{},[264,1105,1106],{},"more processes or threads than expected",[264,1108,1109],{},"runaway memory usage",[264,1111,1112],{},"constant CPU saturation",[264,1114,1115],{},"workers restarting repeatedly",[14,1117,1118],{},"Validate listening sockets:",[26,1120,1122],{"className":28,"code":1121,"language":30,"meta":31,"style":31},"ss -ltnp | grep 8000\nss -lx | grep gunicorn.sock\n",[33,1123,1124,1139],{"__ignoreMap":31},[36,1125,1126,1129,1132,1134,1136],{"class":38,"line":39},[36,1127,1128],{"class":42},"ss",[36,1130,1131],{"class":50}," -ltnp",[36,1133,1053],{"class":518},[36,1135,1056],{"class":42},[36,1137,1138],{"class":50}," 8000\n",[36,1140,1141,1143,1146,1148,1150],{"class":38,"line":54},[36,1142,1128],{"class":42},[36,1144,1145],{"class":50}," -lx",[36,1147,1053],{"class":518},[36,1149,1056],{"class":42},[36,1151,1152],{"class":46}," gunicorn.sock\n",[14,1154,1155],{},"Confirm Gunicorn is listening on the same address or socket Nginx uses.",[14,1157,1158],{},"Check Nginx for upstream-related errors:",[26,1160,1162],{"className":28,"code":1161,"language":30,"meta":31,"style":31},"sudo journalctl -u nginx -n 100 --no-pager\nsudo tail -n 100 \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log\n",[33,1163,1164,1181],{"__ignoreMap":31},[36,1165,1166,1168,1170,1172,1175,1177,1179],{"class":38,"line":39},[36,1167,686],{"class":42},[36,1169,985],{"class":46},[36,1171,988],{"class":50},[36,1173,1174],{"class":46}," nginx",[36,1176,736],{"class":50},[36,1178,147],{"class":50},[36,1180,999],{"class":50},[36,1182,1183,1185,1188,1190,1192],{"class":38,"line":54},[36,1184,686],{"class":42},[36,1186,1187],{"class":46}," tail",[36,1189,736],{"class":50},[36,1191,147],{"class":50},[36,1193,1194],{"class":46}," \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log\n",[14,1196,1002],{},[303,1198,1199,1204,1209,1214],{},[264,1200,1201],{},[33,1202,1203],{},"connect() failed",[264,1205,1206],{},[33,1207,1208],{},"upstream timed out",[264,1210,1211],{},[33,1212,1213],{},"no live upstreams",[264,1215,1216],{},"socket permission errors",[14,1218,1219],{},"Check for OOM events:",[26,1221,1223],{"className":28,"code":1222,"language":30,"meta":31,"style":31},"dmesg -T | grep -i -E 'killed process|out of memory|oom'\n",[33,1224,1225],{"__ignoreMap":31},[36,1226,1227,1230,1233,1235,1237,1240,1243],{"class":38,"line":39},[36,1228,1229],{"class":42},"dmesg",[36,1231,1232],{"class":50}," -T",[36,1234,1053],{"class":518},[36,1236,1056],{"class":42},[36,1238,1239],{"class":50}," -i",[36,1241,1242],{"class":50}," -E",[36,1244,1245],{"class":46}," 'killed process|out of memory|oom'\n",[14,1247,1248],{},"If OOM events exist, lower concurrency or add memory.",[14,1250,1251],{},"Run a baseline load test:",[26,1253,1255],{"className":28,"code":1254,"language":30,"meta":31,"style":31},"hey -n 1000 -c 20 https:\u002F\u002Fyour-domain\u002F\nwrk -t2 -c20 -d30s https:\u002F\u002Fyour-domain\u002F\n",[33,1256,1257,1271],{"__ignoreMap":31},[36,1258,1259,1261,1263,1265,1267,1269],{"class":38,"line":39},[36,1260,733],{"class":42},[36,1262,736],{"class":50},[36,1264,136],{"class":50},[36,1266,741],{"class":50},[36,1268,744],{"class":50},[36,1270,747],{"class":46},[36,1272,1273,1275,1277,1279,1281],{"class":38,"line":54},[36,1274,759],{"class":42},[36,1276,762],{"class":50},[36,1278,765],{"class":50},[36,1280,768],{"class":50},[36,1282,747],{"class":46},[14,1284,1285],{},"If using SQLAlchemy, compare Gunicorn concurrency with the application DB pool size. If concurrency exceeds pool capacity, requests may block even when Gunicorn itself is healthy.",[18,1287,1289],{"id":1288},"checklist","Checklist",[303,1291,1294,1304,1310,1316,1328,1338,1346,1352,1358,1364],{"className":1292},[1293],"contains-task-list",[264,1295,1298,1303],{"className":1296},[1297],"task-list-item",[1299,1300],"input",{"disabled":1301,"type":1302},true,"checkbox"," Gunicorn worker class matches the app workload.",[264,1305,1307,1309],{"className":1306},[1297],[1299,1308],{"disabled":1301,"type":1302}," Worker count is based on CPU and RAM, not guesswork.",[264,1311,1313,1315],{"className":1312},[1297],[1299,1314],{"disabled":1301,"type":1302}," Threads are used only when they improve I\u002FO-bound concurrency.",[264,1317,1319,176,1321,852,1324,1327],{"className":1318},[1297],[1299,1320],{"disabled":1301,"type":1302},[33,1322,1323],{},"timeout",[33,1325,1326],{},"graceful-timeout"," are set deliberately.",[264,1329,1331,176,1333,852,1335,1337],{"className":1330},[1297],[1299,1332],{"disabled":1301,"type":1302},[33,1334,929],{},[33,1336,932],{}," are enabled for long-running stability.",[264,1339,1341,176,1343,1345],{"className":1340},[1297],[1299,1342],{"disabled":1301,"type":1302},[33,1344,175],{}," uses a persistent Gunicorn config file or explicit flags.",[264,1347,1349,1351],{"className":1348},[1297],[1299,1350],{"disabled":1301,"type":1302}," Nginx points to the correct Gunicorn socket or host:port.",[264,1353,1355,1357],{"className":1354},[1297],[1299,1356],{"disabled":1301,"type":1302}," CPU, memory, latency, and error rate were checked after each change.",[264,1359,1361,1363],{"className":1360},[1297],[1299,1362],{"disabled":1301,"type":1302}," Long-running work is removed from request\u002Fresponse paths where possible.",[264,1365,1367,1369],{"className":1366},[1297],[1299,1368],{"disabled":1301,"type":1302}," A rollback configuration is available if tuning degrades performance.",[18,1371,1373],{"id":1372},"related-guides","Related Guides",[303,1375,1376,1382,1388,1392],{},[264,1377,1378],{},[848,1379,1381],{"href":1380},"\u002Fdeploy\u002Fdeploy-flask-with-nginx-plus-gunicorn-step-by-step-guide","Deploy Flask with Nginx + Gunicorn (Step-by-Step Guide)",[264,1383,1384],{},[848,1385,1387],{"href":1386},"\u002Fchecklist\u002Fflask-production-checklist-everything-you-must-do","Flask Production Checklist (Everything You Must Do)",[264,1389,1390],{},[848,1391,856],{"href":855},[264,1393,1394],{},[848,1395,1397],{"href":1396},"\u002Ffix-issues\u002Fflask-gunicorn-service-failed-to-start","Flask Gunicorn Service Failed to Start",[18,1399,1401],{"id":1400},"faq","FAQ",[14,1403,1404,1407,1409,1410,327,1412,1414],{},[267,1405,1406],{},"Q: How many Gunicorn workers should I start with?",[271,1408],{},"\nA: Start with ",[33,1411,326],{},[33,1413,330],{}," workers on a small server, then measure CPU, memory, and latency. Increase gradually only if the system has headroom.",[14,1416,1417,1423,1425,1426,1428],{},[267,1418,1419,1420,1422],{},"Q: When should I use ",[33,1421,243],{},"?",[271,1424],{},"\nA: Use ",[33,1427,243],{}," when requests spend time waiting on a database, API, or filesystem and your app does not require a fully async stack.",[14,1430,1431,1440,1409,1442,1444],{},[267,1432,1433,1434,1436,1437,1439],{},"Q: Should I use ",[33,1435,247],{}," or ",[33,1438,243],{}," for CPU-heavy endpoints?",[271,1441],{},[33,1443,247],{}," for CPU-heavy workloads. Threads usually help less when Python execution is the bottleneck.",[14,1446,1447,1450,1452],{},[267,1448,1449],{},"Q: Does increasing timeout improve performance?",[271,1451],{},"\nA: No. It only allows slow requests to run longer. If the root cause is not fixed, it can reduce available capacity.",[14,1454,1455,1461,1463],{},[267,1456,1457,1458,1460],{},"Q: What does ",[33,1459,932],{}," do?",[271,1462],{},"\nA: It randomizes worker restarts so all workers do not recycle at the same time.",[14,1465,1466,1469,1471,1472,852,1474,395],{},[267,1467,1468],{},"Q: Why is Gunicorn still slow after tuning?",[271,1470],{},"\nA: The bottleneck is often outside Gunicorn: slow SQL queries, external APIs, filesystem latency, missing caching, or proxy configuration. Review ",[848,1473,851],{"href":850},[848,1475,1387],{"href":1386},[18,1477,1479],{"id":1478},"final-takeaway","Final Takeaway",[14,1481,1482],{},"Gunicorn tuning is controlled capacity planning, not random flag changes. Start with a conservative baseline, match the worker model to the workload, measure under load, and adjust one variable at a time. If tuning does not improve results, the bottleneck is usually in application code, the database, or reverse proxy configuration rather than Gunicorn itself.",[1484,1485,1486],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":31,"searchDepth":54,"depth":54,"links":1488},[1489,1490,1491,1492,1493,1494,1495,1496,1497],{"id":20,"depth":54,"text":21},{"id":251,"depth":54,"text":252},{"id":258,"depth":54,"text":259},{"id":875,"depth":54,"text":876},{"id":959,"depth":54,"text":960},{"id":1288,"depth":54,"text":1289},{"id":1372,"depth":54,"text":1373},{"id":1400,"depth":54,"text":1401},{"id":1478,"depth":54,"text":1479},"Complete guide on flask gunicorn performance tuning guide for Flask production environments.","md",{"ogTitle":5,"ogDescription":1498,"twitterCard":1501,"robots":1502,"canonical":1503},"summary_large_image","index, follow","https:\u002F\u002Fflask-deployment.com\u002Foptimize\u002Fflask-gunicorn-performance-tuning-guide","\u002Foptimize\u002Fflask-gunicorn-performance-tuning-guide",{"title":5,"description":1498},"optimize\u002Fflask-gunicorn-performance-tuning-guide","qfJREuj4f4HCj0akNNPkJQLYeVBHZAme-h3r-Va_9vA",1776805765059]