Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Working with Node.js
      • Troubleshooting Node.js Apps
      • Node.js Behavior in Heroku
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Model Context Protocol
    • Vector Database
    • Heroku Inference
      • Inference API
      • Quick Start Guides
      • AI Models
      • Inference Essentials
    • Working with AI
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Language Support
  • Python
  • Optimizing Python Application Concurrency

Optimizing Python Application Concurrency

English — 日本語に切り替える

Last updated December 03, 2024

Table of Contents

  • Default Settings and Behavior
  • Tuning the Concurrency Level

Web applications that process incoming HTTP requests concurrently make more efficient use of dyno resources than web applications that only process one request at a time. We recommend using web servers that support concurrent request processing for developing and running production services.

The Django and Flask web frameworks feature convenient built-in web servers, but these blocking servers only process a single request at a time. If you deploy with one of these servers on Heroku, your dyno resources is underutilized and your application feels unresponsive.

Instead, we recommend that you use either Gunicorn or Uvicorn, which are performant Python HTTP servers for WSGI or ASGI applications. They allow you to run any Python application concurrently by running multiple Python processes within a single dyno.

Read Deploying Python Applications with Gunicorn to learn how to set up Gunicorn for Python on Heroku.

Default Settings and Behavior

If your application uses multiple buildpacks, ensure that the Python buildpack, as the primary language buildpack of your application, executes after other language buildpacks. Otherwise, the app’s WEB_CONCURRENCY can default to the value set by a buildpack that runs after the Python one.

When booting an application, the Heroku Python buildpack automatically detects the CPU and memory specifications of the current dyno type. It sets the WEB_CONCURRENCY environment variable to a suitable default value:

Common Runtime

Dyno TypeDefault WEB_CONCURRENCY
Eco, Basic, Standard-1X2
Standard-2X4
Performance-M5
Performance-L17
Performance-L-RAM9
Performance-XL17
Performance-2XL33

Private Spaces and Shield Private Spaces

We don’t set a WEB_CONCURRENCY environment variable for Fir dynos.

Dyno TypeDefault WEB_CONCURRENCY
Private-S / Shield-S4
Private-M / Shield-M5
Private-L / Shield-L17
Private-L-RAM / Shield-L-RAM9
Private-XL / Shield-XL17
Private-2XL / Shield-2XL33

Both Gunicorn and Uvicorn will automatically use the value set by the WEB_CONCURRENCY environment variable to control the level of concurrency, or the number of child processes the parent process launches.

If your app uses a different web server, you must configure it to use the value set by WEB_CONCURRENCY for its number of workers. For example, if the server supports a --workers CLI argument, add --workers $WEB_CONCURRENCY to the server command listed under the web process in your Procfile.

The default WEB_CONCURRENCY value is not visible in your app’s config vars, since it is set directly in the dyno environment by the Python buildpack when each dyno boots. This ensures the value adjusts automatically if you change the size of an app’s dyno, or use more than one size of dyno at once.

Tuning the Concurrency Level

Each app has unique memory, CPU, and I/O requirements, so there’s no such thing as a one-size-fits-all scaling solution. The Heroku Python buildpack provides reasonable default concurrency values for each dyno type, but some apps benefit from fine-tuning the concurrency level. See Application Load Testing for guidance on fine-tuning your application.

To manually set the number of child processes running your application, adjust the WEB_CONCURRENCY environment variable by setting a config var.

For instance, to statically set the number of child processes to 8, use:

$ heroku config:set WEB_CONCURRENCY=8

If you set WEB_CONCURRENCY to a fixed value, remember to adjust it when you scale to a different dyno type to optimize the use of the available RAM and CPUs on the new dyno type.

For Django-specific recommendations, see Concurrency and Database Connections in Django.

Keep reading

  • Python

Feedback

Log in to submit feedback.

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices