Change in default `WEB_CONCURRENCY` for Python apps

Change effective on 13 March 2024

We changed the default WEB_CONCURRENCY value for dynos running Python apps to more closely reflect the performance characteristics of the dyno type.

When a Python app boots, if it’s not already set, the Python buildpack automatically sets the WEB_CONCURRENCY environment variable to a suitable default value based on the dyno type. Some Python web servers, such as Gunicorn or Uvicorn, use this value to set the number of child processes launched to serve requests.

Here are the default WEB_CONCURRENCY values set by the Python buildpack:

Common Runtime

Dyno TypeOld Default WEB_CONCURRENCYNew Default WEB_CONCURRENCY
Eco, Basic, Standard-1X22 (unchanged)
Standard-2X44 (unchanged)
Performance-M85
Performance-L1117

Private Spaces and Shield Private Spaces

Dyno TypeOld Default WEB_CONCURRENCYNew Default WEB_CONCURRENCY
Private-S / Shield-S44 (unchanged)
Private-M / Shield-M85
Private-L / Shield-L1117

These changes take effect the next time your app builds and deploys.

In addition, the Python buildpack now outputs the chosen concurrency value to the app’s startup logs, for web dyno types only, to aid debugging:

2024-03-12T16:36:36 app[web.1]: Python buildpack: Defaulting WEB_CONCURRENCY to 5 based on the number of CPU cores.

To override these new default values, set WEB_CONCURRENCY as an explicit config var on your app to its previous value.

For example, to set an app using Performance-M web dynos to the previous concurrency level, use:

$ heroku config:set WEB_CONCURRENCY=8

The web dyno logs shows that manually setting the value prevents the default values from getting configured when the app boots:

2024-03-12T16:36:51 app[web.1]: Python buildpack: Skipping automatic configuration of WEB_CONCURRENCY since it's already set.

For more information, see Optimizing Python Application Concurrency.