# Dash callbacks are not async - handling multiple requests and callbacks in parallel

**URL:** <https://community.plotly.com/t/dash-callbacks-are-not-async-handling-multiple-requests-and-callbacks-in-parallel/5848>\
**Category:** Dash Python\
**Created:** [September 19, 2017, 5:35pm UTC](https://community.plotly.com/t/dash-callbacks-are-not-async-handling-multiple-requests-and-callbacks-in-parallel/5848 "2017-09-19T17:35:44Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![dolph54](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@dolph54](https://community.plotly.com/u/dolph54)\
**Post date:** [September 19, 2017, 5:35pm UTC](https://community.plotly.com/t/dash-callbacks-are-not-async-handling-multiple-requests-and-callbacks-in-parallel/5848/1 "2017-09-19T17:35:44Z")

</div>

I have two callbacks bound to the same input component (html.Button: n\_clicks) and it seems that one blocks the other (I’ve tested using time.sleep). Is this intended? I need one callback to be executed first, but the order seems to be quite random. If it were async, I could use a semaphore. I’m using app.run\_server(debug=True) and have tried threaded=True, but that seems to be the default

---

<div class="post-metadata">

**Author:** ![chriddyp](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/chriddyp/32/16855_2.png) [@chriddyp](https://community.plotly.com/u/chriddyp)\
**Post date:** [September 19, 2017, 6:24pm UTC](https://community.plotly.com/t/dash-callbacks-are-not-async-handling-multiple-requests-and-callbacks-in-parallel/5848/2 "2017-09-19T18:24:30Z")

</div>

Yes, this is intended. To enable your dash app to handle multiple callbacks in parallel, run the app using `gunicorn` like:

```auto
# in file app.py
server = app.server

```

```auto
$ gunicorn app:server # app refers to app.py, server refers to the variable

```

Or run with multiple processes:

```auto
app.run_server(debug=True, processes=4)

```

For production applications, it’s recommended that you use gunicorn. For more, see [https://plot.ly/dash/deployment](https://plot.ly/dash/deployment).

---

<div class="post-metadata">

**Author:** ![nedned](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/nedned/32/8795_2.png) [@nedned](https://community.plotly.com/u/nedned)\
**Post date:** [September 20, 2017, 6:48am UTC](https://community.plotly.com/t/dash-callbacks-are-not-async-handling-multiple-requests-and-callbacks-in-parallel/5848/3 "2017-09-20T06:48:28Z")

</div>

My understanding is that gunicorn defaults to 1 worker process, so just using it out of the box as you indicate won’t allow your app to handle multiple callbacks in parallel. To specify multiple workers just do:

```
$ gunicorn -w 2 app:server

```

In my experience this will break the CSRF protection that Dash automatically adds to Flask, as the different workers are initialised with different tokens. For this to work, you’ll need to either explicitly supply your own CSRF token or as a simple/hacky workaround you can specify that gunicorn forks the Python process _after_ the app is loaded thereby ensuring the workers share the same CSRF token:

```
$ gunicorn -w 2 --preload app:server

```

This Dash Issue contains a discussion of all that: [https://github.com/plotly/dash/issues/132](https://github.com/plotly/dash/issues/132)

Depending in what your callbacks are doing, using asynchronous worker(s) with multiple threads might be useful. There are different types of async workers, here’s how you can use the gevent one:

```
$ pip install gunicorn gevent
$ gunicorn --worker-class gevent --threads 8

```

You can also combine to have multiple async worker processes.

---

<div class="post-metadata">

**Author:** ![dolph54](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@dolph54](https://community.plotly.com/u/dolph54)\
**Post date:** [September 20, 2017, 2:04pm UTC](https://community.plotly.com/t/dash-callbacks-are-not-async-handling-multiple-requests-and-callbacks-in-parallel/5848/4 "2017-09-20T14:04:16Z")

</div>

Thanks. It looks like all these solutions don’t work on Windows (which I need for other dependencies in my app). gunicorn is Linux only and the processes=4 kwarg requires os.fork which is missing in Windows. Is there a Windows alternative for this (simpler the better)?

---

<div class="post-metadata">

**Author:** ![dolph54](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@dolph54](https://community.plotly.com/u/dolph54)\
**Post date:** [September 20, 2017, 2:37pm UTC](https://community.plotly.com/t/dash-callbacks-are-not-async-handling-multiple-requests-and-callbacks-in-parallel/5848/5 "2017-09-20T14:37:50Z")

</div>

I also gave gevent’s WSGI server a try and it just completely freezes up trying to switch greenlets (see code below).

[edit] Fixed the code below to use the flask server but doesn’t run async. Also, tried Twisted which runs fine but callbacks are still single-threaded.  
**[edit 2] I’ve tried gevent.WSGIServer, Tornado, Twisted, and mtwsgi (with 10 threads). All run the Dash app, but none run callbacks async**

Why isn’t it possible to just use threading with Werkzeug? - that seems like it would be by far the simplest solution (and helpful to many, who are just running small scale apps). For some reason, the “threaded=True” parameter in app.run\_server doesn’t seem to have an effect.

```
from gevent import monkey
monkey.patch_all()

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
from gevent.wsgi import WSGIServer

server = flask.Flask( __name__ )
app = dash.Dash( __name__ , server=server)

app = dash.Dash()

app.layout = html.Div([
    dcc.Input(id='my-id', value='initial value', type="text"),
    html.Div(id='my-div')
])

@app.callback(
    Output(component_id='my-div', component_property='children'),
    [Input(component_id='my-id', component_property='value')]
)
def update_output_div(input_value):
    return 'You\'ve entered "{}"'.format(input_value)

if __name__ == ' __main__':
    http_server = WSGIServer((127.0.0.1'', 8050), server)
    http_server.serve_forever()
```

---

<div class="post-metadata">

**Author:** ![chriddyp](https://sea2.discourse-cdn.com/flex024/user_avatar/community.plotly.com/chriddyp/32/16855_2.png) [@chriddyp](https://community.plotly.com/u/chriddyp)\
**Post date:** [September 25, 2017, 6:45pm UTC](https://community.plotly.com/t/dash-callbacks-are-not-async-handling-multiple-requests-and-callbacks-in-parallel/5848/6 "2017-09-25T18:45:38Z")

</div>

> [@dolph54](#):
>
> Why isn’t it possible to just use threading with Werkzeug?

I’m not sure why this doesn’t work for you. This example works for me on my mac:

```auto
import dash
import dash_core_components as dcc
import dash_html_components as html

import time

app = dash.Dash()
server = app.server

app.layout = html.Div([
    dcc.Input(id='input'),
    html.Div(id='output')
])

@app.callback(
    dash.dependencies.Output('output', 'children'),
    [dash.dependencies.Input('input', 'value')])
def update_output(value):
    print('Request')
    time.sleep(20)
    return value

if __name__ == ' __main__':
    app.run_server(threaded=True)

```

 ![dash-threaded](https://us1.discourse-cdn.com/flex024/uploads/plot/original/2X/4/4df5c6e4789c4da2a53a7ff443c60d915735885d.gif)

> [@dolph54](#):
>
> Is there a Windows alternative for this (simpler the better)?

From [Reddit - Dive into anything](https://www.reddit.com/r/learnpython/comments/3fr2a8/windows_alternative_to_gunicorn_deploying_on/), some folks recommend [Waitress](https://docs.pylonsproject.org/projects/waitress/en/latest/). I ran the previous example with waitress with:

```auto
$ waitress-serve --threads=6 my_app:server

```

where `my_app` refers to a file called `my_app.py`. I haven’t verified this on Windows.

 ![waitress](https://us1.discourse-cdn.com/flex024/uploads/plot/original/2X/a/a29f50e22a2990026bb157688ebe21d524775a67.gif)

---

<div class="post-metadata">

**Author:** ![Soerendip](https://avatars.discourse-cdn.com/v4/letter/s/d2c977/32.png) [@Soerendip](https://community.plotly.com/u/Soerendip)\
**Post date:** [December 21, 2019, 4:52pm UTC](https://community.plotly.com/t/dash-callbacks-are-not-async-handling-multiple-requests-and-callbacks-in-parallel/5848/7 "2019-12-21T16:52:15Z")

</div>

I tried waitress with

```
    waitress.serve(app.server, threads=4)

```

but the callbacks are not executed on different cpus. And the single cpu load stays under 100% all the time. I think multithreading is not working correctly. Or is it only working with gunicorn?

The only thing that worked so far is the development server

```
app.run_server(debug=True, threaded=False, processes=n_cpu)
```
