After research, I think the best way to have Flask + Bokeh Server running in Heroku within a single Heroku App is by setting up a reverse-proxy server such as NGINX and running the Bokeh Server behind NGINX.
For anyone interested in my first post, I did try to run a reverse-proxy with Flask only. I was able to do the HTTP part, but it got more and more complex when I started handling the WebSocket connection between the Bokeh Server and the Client Browser. Here is what I learned:
sequenceDiagram
participant A as Client Browser
participant B as Bokeh Server <bkapp>
A->>B: HTTP Request bkapp/autoload.js <params>
B->>A: HTTP Response bkapp/autoload.js script
A->>B: HTTP Request bkapp/ws
B->>A: HTTP Response Can "Upgrade" only to "WebSocket"
A->>B: WebSocket connect
B->>A: WebSocket connection handshake
B->>A: WebSocket <json> messages from Bokeh to Browser
A->>B: WebSocket <json> messages from Browser to Bokeh
The HTTP part can be handled by Flask with very little overhead, but the WebSocket part, I tried Tornado WSGIContainer, but Tornado’s own documentation explains that it will not scale as Flask would. I also tried Flask-SocketIO and Flask-SocketIO-Client. At this point, the solution explained in Bokeh documentation with Apache, NGINX or establishing an SSL tunnel look way more simpler.