We’ve created an R Shiny app for viewing data. On the server we log the time needed to query the database. The users report longer waiting times than the query time we log. What is R Shiny doing?
Looking under the hood of R Shiny we discovered it uses websockets for communication. (https://unleash-shiny.rinterface.com/shiny-intro.html#debug-websocket-with-shiny) There is a way to see the messages send back-and-forth in the developer tools network tab. Red is download and green is upload.

We can see that a query that takes 0.1 seconds takes 1.2 seconds (previous green message until last red message) before the user sees the result. This is caused by the amount of data that is returned. The difference of 1 second is not something a user wil notice.
Imagine a query that takes 3 seconds and produces a lot of data. Then the user will wait for a lot longer and the query time is way off from what the user experiences. Also the rendering of the actual table will be slower since it has more data to process. We need to know the time it takes to show the data to the user.
The data is displayed with DT (https://rstudio.github.io/DT/) which has all sorts of events. The callback is most promising and fires some javascript after the data is presented to the user. So we wrote some code to send this event back to the server and log the time it needed for the data to be send and the callback was fired. The code looked something like this:
library(DT)
js <- c(
"var start = DATE_FROM_SERVER_HERE;",
"Shiny.onInputChange('render_done', start);"
)
ui <- fluidPage(
DTOutput("table")
)
server <- function(input, output, session){
observeEvent(input$render_done, { HANDLE_LOGGING_OF_TIME_NEEDED })
output[["table"]] <- renderDT({
datatable(
iris,
callback = JS(js)
)
})
}
shinyApp(ui, server)
We now have a better understanding of the user experience when it comes to response times. The query was fast enough, but the rendering took too long. Now we can start fixing this.