✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🐇 Announcing Dash VTK for 3d simulation graphics. Check out the March webinar.

Browser page loading too slow, after adding many callbacks

I am trying to build a complex admin panel with a lot of pages, using dash.
I am using dash’s dynamic layout to load the multi-page environment.

After adding in my app 10 callbacks with 10-20 inputs/states and 10-30 outputs each, the initial page load takes about 2 seconds.
If I increase the number of callbacks to 100, just to stress test the plotly dash, the browser takes around 90 seconds to load.
If I continue the development that way, my app will be practically unusable after some more pages implementation.

As I can guess, dash tries to pre-load and prepare all of the callbacks when the page loads, no matter if the user will need them in the current page.
Is there something I can do to make that perform better or it is just a limitation of the current version (running 1.12) of dash?
Perhaps sending to the browser only the callbacks that every page needs… But I can’t find such an option in dash documentation…

Thank you!

The actual callback definitions aren’t very large so the network cost is relatively small. It’s more inefficiencies in dash’s code when you add hundreds of callbacks. We plan on speeding things up for this use case eventually. In the meantime, apps that have hundreds of callbacks frequently can use the (new!) pattern matching callback pattern, which will speed things up and improve your code (no longer need to generate callbacks dynamically): https://dash.plotly.com/pattern-matching-callbacks

I am already using the new pattern matching callback pattern, it really helps indeed!
All these numbers I am giving you are the bare minimum for my app, I can’t find a way to use less, because there are so many different components in it and of course every component has it own special properties that I can’t use pattern matching.
So unfortunately, I guess that dash can’t match the requirements of my app at the current version.

Anyway, it is good to hear that there are plans for optimizations!
Is it a work in progress? Do you track those updates in a branch in your github?

Thank you for your reply!

there isn’t any work in progress right now for this use case, but we are working on some code to improve the performance when there are many elements on the page, which may help your use case. This is the PR for that work: https://github.com/plotly/dash/pull/1254

Performance optimization is a long and deep rabbit hole, so this is work that may wait until enough Dash Enterprise customers request it or an organization with a software budget fund its development: https://plotly.com/products/consulting-and-oem

1 Like

Do you need to keep everything in one app? Otherwise, you might be able to speed up the initial load by splitting the code into multiple apps.

This is a temporary workaround that worth a shot. I could try to split the admin panel with the user panel via two separated dash apps and a flask route for each one of them. But it is only here for the short-term. When the app will grow, the problem will be still there.
Thanks for the advice.

The prevent_initial_call keyword argument for callbacks was added in Dash v1.12.0. Set this argument to True for all of your pattern matching callbacks (or any callbacks that don’t need to fire when the page loads) to prevent them all from sending requests to the server and waiting for responses at the same time.

Here’s an example of the prevent_initial_call keyword argument.

@app.callback(
    Output({"type": "content_task", "id": MATCH}, "is_open"),
    Input({"type": "form_task", "id": MATCH}, "is_open"),
    prevent_initial_call=True
)
def update_content_task(form_is_open):
    return not form_is_open