Bokeh slow for 3 or more users

Hi all,
I’m experiencing a problem with the Bokeh server when 3 or more users connect at the same time. The slowness lead to interruption of the session with little to no interactivity. Checking out the resources, the memory and cpu are well-managed. My conclusion lead me to question Bokeh’s performance. Are there any parameters I can possibly add to provide better resources or improvement?

1 Like

Hi @simonay

Issues can be caused by many things including your code, Panel/ Bokeh code, the resources (like databases) you use, the way you deploy (server, network etc.) and more.

Without more info it would be really hard to give you some advice. Is it possible for you to create a minimum, reproducible example?

As for resources, I can assure you that the memory is not near its max capacity nor is the CPU loading much effort. As for the network, I tried running the users from abroad and next to the server room. Currently, the deployed webapp is running on a Linux service with a panel command that shares what websocket origin to allow, port number, oauth extra params, client key and secret. I will be adding an Nginx configuration file as a reverse proxy along with an SSL certificate accordingly.

As for the code structure I will share an idea on how it is built. We request user information to authorize the specified dashboards for the user; the buttons dedicated for each dashboard is set in the sidebar, the content is inside - all of which is using the Material Template.

Code Snippet:

response = requests.get(configuration(key = 'KEY', name = 'name'), headers={'Authorization': 'Bearer ' + pn.state.access_token})
pn.state.cache['user_info'] = json.loads(response.content)
homepage_content = "# Welcome!"

homepage = pn.pane.Markdown(homepage_content)
loading_widget = pn.indicators.LoadingSpinner(value=True, color = 'success', bgcolor = 'light')
loading_comment = pn.pane.Markdown("**Loading...**")
loading_page = pn.Column(loading_widget, loading_comment)
main_layout = pn.Column(homepage, sizing_mode='stretch_both')

homepage_btn = pn.widgets.Button(name = 'Homepage', button_type = 'primary', stylesheets=[sidebar_btn_text_css])

btn1 = pn.widgets.Button(name = 'Dashboard 1', button_type = 'success')
btn2 = pn.widgets.Button(name =  'Dashboard 2', button_type = 'success')

from Dashboards import Dashboard1, Dashboard2, Home

buttons = {'dash1': btn1, 'dash2': btn2, 'homepage': homepage_btn}
dashboards = {'dash1': Dashboard1, 'dash2': Dashboard2, 'homepage': Home}

global new_dashboard
new_dashboard = None

def show_dashboard(dashboard_key, new_dashboard):
    main_layout[0] = loading_page
    new_dashboard = dashboards[dashboard_key]
    if dashboard_key == 'homepage':
        main_layout[0] = new_dashboard
        main_layout[0] = new_dashboard.layout(user_info)

buttons['homepage'].on_click(lambda event: show_dashboard('homepage', new_dashboard))
buttons['btn1'].on_click(lambda event: show_dashboard('btn1', new_dashboard))
buttons['btn2'].on_click(lambda event: show_dashboard('btn2', new_dashboard))

template = pn.template.MaterialTemplate(
    title = 'Title',
    sidebar = [homepage_btn, btn1, btn2],
    main = [main_layout],

template.base_url = '/'

Dashboard1 and Dashboard2 are just pn.Tabs containing Filters and some plots. In the original webapp, I have several dashboards some are lighter than others. Their performance work really well with a single user. It’s just when we have multiple users, things crash or just freeze.

Check out Launch a server on the command line — Panel v1.4.0 for commands like --num-threads

Try profiling. Enable Profiling and Debugging — Panel v1.4.0
I am always surprised by what actually slows down performance for my apps.


The code below could be problematic depending on the code in the Dashboards module.

I would expect that you are reusing the same Dashboard1 instance for all users. That is not what you should do.

Maybe it can help to study the Grasp Panel Execution section to understand the difference between code in your imported modules and the served file.

Hi @Marc,

Thanks for sharing your insight! It happened that I tested this out before and made sure that for the same dashboard, say Dashboard1 module, is authorized differently between two users. That way I would know if changes are being made for both at the layout method according the user_info argument since it changes at the serving file level. I hope this answers your concern, your confirmation would help.

As for the remaining suggestions, I will try them tomorrow and get back to you. Thanks everyone!

I tried --num-threads, it didn’t help much. The webapp still crashes on 4 users. What is the right number of threads should I specify? as for --num-procs would it help in any way?


The admin page is crashing along with the server :frowning:

New information came to light!
The buttons are waiting for each other to finish. In a sense, when 2 users click, one button starts and the other button waits and executes after the first button’s callback method finishes. How do you think I can make it work separately?

@Marc , your suspicion is very close!