Deploying a Shiny App

· 4 min read · Updated March 7, 2026 · intermediate
shiny deployment shinyapps.io rstudio-connect hosting

You’ve built an amazing Shiny app locally—now it’s time to share it with the world. Deployment is the final step in the Shiny development workflow, and fortunately R makes this remarkably straightforward. In this tutorial, we’ll cover the three most popular deployment platforms: shinyapps.io, RStudio Connect, and Docker-based deployments.

Prerequisites

Before deploying your app, ensure you have:

  • A working Shiny app in a standalone script (app.R) or as a folder with app.R and www/ assets
  • An account on your chosen deployment platform
  • The rsconnect package installed:
install.packages("rsconnect")

Deploying to shinyapps.io

shinyapps.io is the easiest way to deploy Shiny apps. It’s a hosted service by Posit (formerly RStudio) that handles all server infrastructure for you.

Step 1: Connect Your Account

First, authorize rsconnect to access your shinyapps.io account:

library(rsconnect)
rsconnect::setAccountInfo(name = "your-account-name", 
                          token = "YOUR_TOKEN", 
                          secret = "YOUR_SECRET")

You get these credentials from your shinyapps.io dashboard under the “Tokens” tab.

Step 2: Deploy Your App

Deploying is a single function call:

library(shiny)
rsconnect::deployApp("path/to/your/app")

For a simple app.R in your current directory:

rsconnect::deployApp(".")

The first deployment uploads all your app’s dependencies, which may take a minute. Subsequent deployments are faster since rsconnect caches unchanged files.

Example: Deploying the diamonds explorer

# Create a simple app
ui <- fluidPage(
  titlePanel("Diamond Explorer"),
  selectInput("cut", "Select Cut:", choices = unique(diamonds$cut)),
  plotOutput("hist")
)

server <- function(input, output) {
  output$hist <- renderPlot({
    library(ggplot2)
    ggplot(diamonds[diamonds$cut == input$cut, ], 
           aes(carat)) + geom_histogram()
  })
}

shinyApp(ui, server)

# Deploy it
rsconnect::deployApp(".")

After deployment, you’ll receive a URL like https://your-name.shinyapps.io/diamond-explorer/.

Deploying to RStudio Connect

RStudio Connect is a professional platform for sharing data products within organizations. It supports Shiny apps, R Markdown reports, APIs, and more.

Configuration

First, configure the server connection:

rsconnect::connectServer(url = "https://your-server.com",
                         apiKey = "your-api-key")

Get your API key from the RStudio Connect user settings.

Deployment

Deploy using the same deployApp() function:

rsconnect::deployApp("path/to/app",
                     server = "your-server-name",
                     account = "your-username")

Access Control

RStudio Connect lets you control who accesses your app:

# Make app visible to specific users
rsconnect::setAccessRecord(
  appName = "my-shiny-app",
  users = c("user1@company.com", "user2@company.com"),
  accessType = "viewer"
)

Docker Deployment

For maximum control, deploy Shiny apps in Docker containers. This works on any cloud platform (AWS, GCP, Azure, DigitalOcean).

Create a Dockerfile

FROM rocker/shiny-verse:latest

# Install dependencies
RUN R -e "install.packages(c('shiny', 'ggplot2', 'dplyr'))"

# Copy app files
COPY app.R /srv/shiny/
COPY www /srv/shiny/www/

# Expose port
EXPOSE 3838

# Run Shiny Server
CMD ["R", "-e", "shiny::runApp('/srv/shiny', port = 3838, host = '0.0.0.0')"]

Build and Run

docker build -t my-shiny-app .
docker run -p 3838:3838 my-shiny-app

Push to Container Registry

docker tag my-shiny-app registry.example.com/my-shiny-app:latest
docker push registry.example.com/my-shiny-app:latest

Deployment Best Practices

1. Use renv for Reproducibility

The renv package locks your dependencies to ensure consistent behavior:

install.packages("renv")
renv::init()
renv::snapshot()

Commit renv.lock to version control. When deploying, rsconnect uses this file to install exact package versions.

2. Handle Secrets Properly

Never hardcode API keys or passwords in your app. Use environment variables:

api_key <- Sys.getenv("MY_API_KEY")

On shinyapps.io, add secrets via the dashboard’s “Variables” tab.

3. Optimize App Size

Large apps take longer to deploy. Remove unnecessary packages:

# Instead of library(ggplot2), use specific imports
library(dplyr, exclude = "filter")

4. Set Appropriate Resources

In shinyapps.io, configure instance size based on your app’s needs:

PlanMemoryConcurrent Users
Free1 GB25
Starter2 GB50
Professional8 GB200

Troubleshooting Deployment Issues

Package Not Available

If deployment fails with “package X is not available”:

  • Check the package supports your R version
  • Verify the package is on CRAN or a valid repository
  • For GitHub packages, use install_github() in your app before deploying

App Loads but Shows Errors

Enable debugging:

rsconnect::deployApp(".", 
                     appName = "my-app",
                     launch.browser = FALSE,
                     lint = TRUE)

Connection Timeout

Increase the timeout in your rsconnect configuration or switch to a larger instance plan.

Updating Your Deployed App

After making changes to your app locally, redeploy with the same command:

rsconnect::deployApp(".")

The rsconnect package detects changes and uploads only modified files. To force a full redeploy (useful if dependency issues occur):

rsconnect::deployApp(".", forceRebuild = TRUE)

Scheduling and Background Tasks

RStudio Connect supports scheduled rendering and background jobs. This lets your app refresh data periodically:

# In an R Markdown report context
rmarkdown::render("report.Rmd",
                  params = list(refresh = TRUE))

Set up schedules through the RStudio Connect dashboard for automatic report generation.

Summary

Deploying Shiny apps is straightforward with the right platform:

  • shinyapps.io: Easiest—fully managed, great for learning and small projects
  • RStudio Connect: Best for organizations needing security and access control
  • Docker: Maximum flexibility for custom infrastructure

Key takeaways:

  • Use rsconnect::deployApp() for most deployments
  • Leverage renv for reproducible environments
  • Store secrets in environment variables, never in code

Your app is now live and accessible to the world!