Improving scalability with async programming

Asynchronous programming is a powerful but advanced technique for increasing the scalability of your Shiny apps. On its own, async programming doesn’t increase the performance or responsiveness for a single user of your app, but can improve responsiveness (dramatically, in some cases) when multiple users are active at the same time.
Author

Joe Cheng

Published

October 15, 2019

Before we begin

Please be aware that the Extended Tasks feature is now our recommended starting point for performing long-running operations in Shiny. Extended Tasks can be used not only to allow multiple sessions to run concurrently, but also let a given session run long-running operations without blocking its own reactives.

There are still scenarios that require the use of async programming, and it remains a fully supported feature of Shiny, but we recommend starting with Extended Tasks first.

Asynchronous programming is a powerful but advanced technique for increasing the scalability of your Shiny apps (starting with the Shiny 1.1.0 release). On its own, async programming doesn’t increase the performance or responsiveness for a single user of your app, but can improve responsiveness–dramatically, in some cases–when multiple users are active at the same time.

Async programming is mainly effective when your app has one, or two, or a few spots where a lot of time is spent. This might be where you download a large amount of data from a web API, or run a slow query against a remote database, or ferret through a directory full of thousands of log files. You can use async to offload this kind of work to a background R process, leaving Shiny free to service other users while it waits for those calculations to complete.

Shiny integrates with the promises package, which you’ll need to become intimately familiar with if you want to take advantage of async programming.

Optimize first!

If your app doesn’t scale well and you don’t yet know why, stop and figure that out first! Async programming should be your last resort in fixing performance and scalability problems. If you haven’t tried profiling and removing common bottlenecks, definitely do that first, and only turn to async programming if you’re sure the long-running tasks you’re trying to offload are already run as quickly and as seldom as possible.

Watch the talk

For a quick introduction to async programming with Shiny, check out this video introducing the feature at rstudio::conf 2018:

Get started

If you’re ready to get started learning about async programming in earnest, you’ll find all the documentation you need at the promises site. Async programming is an advanced technique, so we highly recommend you read through the entire six-part article series there!