Deep-dive on the Next Gen Platform. Join the Webinar!

Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Working with Node.js
      • Troubleshooting Node.js Apps
      • Node.js Behavior in Heroku
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Working with AI
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • App Performance
  • Using AWS S3 to Store Static Assets and File Uploads

Using AWS S3 to Store Static Assets and File Uploads

English — 日本語に切り替える

Last updated December 19, 2024

Table of Contents

  • Overview
  • Setting Up S3 for Your Heroku App
  • Manually Uploading Static Assets
  • Uploading Files From a Heroku App
  • Language-Specific Guides
  • Referring to Your Assets

Amazon Simple Storage Service (S3) is a durable and available store, ideal for storing application content like media files, static assets, and user uploads.

Storing static files elsewhere is crucial for Heroku apps since dynos have an ephemeral filesystem. Whenever you replace a dyno or when it restarts, which happens daily, all files that aren’t part of your application’s slug are lost. Use a storage solution like S3 to offload the storage of static files from your app.

To add S3 to your app without creating an AWS account, see the Bucketeer add-on.

Overview

All files sent to S3 get stored in a bucket. Buckets act as a top-level container, much like a directory, and its name must be unique across all of S3. A single bucket typically stores the files, assets, and uploads for an application. An Access Key ID and a Secret Access Key govern access to the S3 API.

Setting Up S3 for Your Heroku App

Enabling an application to use S3 requires that the application have access to your AWS credentials and the name of the bucket to store files.

It’s recommended to create an IAM user to use its credentials with your Heroku app. Avoid using your root AWS credentials.

Configure Credentials

You can find your S3 credentials in My Security Credentials section of AWS.

Never commit your S3 credentials to version control. Set them in your config vars instead.

Use the heroku config:set to set both keys:

$ heroku config:set AWS_ACCESS_KEY_ID=MY-ACCESS-ID AWS_SECRET_ACCESS_KEY=MY-ACCESS-KEY
Adding config vars and restarting app... done, v21
  AWS_ACCESS_KEY_ID     => MY-ACCESS-ID
  AWS_SECRET_ACCESS_KEY => MY-ACCESS-KEY

Name Your Bucket

Create your S3 bucket in the same region as your Heroku app to take advantage of AWS’s free in-region data transfer rates.

To create a bucket, access the S3 section of the AWS Management Console and create a new bucket in the US Standard region:

Create new S3 bucket

Follow AWS’ bucket naming rules to ensure maximum interoperability.

Store the bucket name in a config var to give your application access to its value:

$ heroku config:set S3_BUCKET_NAME=example-app-assets
Adding config vars and restarting app... done, v22
  S3_BUCKET_NAME     => example-app-assets

Manually Uploading Static Assets

You can manually add static assets such as videos, PDFs, Javascript, CSS, and image files using the command line or the Amazon S3 console.

Uploading Files From a Heroku App

There are two approaches to processing and storing file uploads from a Heroku app to S3: direct and pass-through. See the language guides for specific instructions.

Direct Uploads

In a direct upload, a file uploads to your S3 bucket from a user’s browser, without first passing through your app. Although this method reduces the amount of processing your application needs to perform, it can be more complex to implement. It also limits the ability to modify files before storing them in S3.

Pass-Through Uploads

In a pass-through upload, a file uploads to your app, which in turn uploads it to S3. This method enables you to perform preprocessing on user uploads before you push them to S3. Depending on your chosen language and framework, this method can cause latency issues for other requests while the upload takes place. Use background workers to process uploads to free up your app.

It’s recommended to use background workers for uploading files. Large files uploads in single-threaded, non-evented environments, like Rails, block your application’s web dynos and can cause request timeouts. EventMachine, Node.js and JVM-based languages are less susceptible to such issues.

Language-Specific Guides

Here are language-specific guides to handling uploads to S3:

Language/Framework Tutorials
Ruby/Rails
  • Direct to S3 Image Uploads in Rails
Node.js
  • Direct to S3 File Uploads in Node.js
Python
  • Direct to S3 File Uploads in Python
PHP
  • Uploading Files to S3 in PHP

Referring to Your Assets

You can use your assets’ public URLs, such as https://s3.amazonaws.com/bucketname/filename, in your application’s code. S3 directly serves these files, freeing up your application to serve only dynamic requests.

For faster page loads, consider using a content delivery service, such as Amazon Cloudfront to serve your static assets instead.

Keep reading

  • App Performance

Feedback

Log in to submit feedback.

Worker Dynos, Background Jobs and Queueing Worker Dynos, Background Jobs and Queueing

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices