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
    • Model Context Protocol
    • Vector Database
    • Working with AI
    • Heroku Inference
      • Quick Start Guides
      • Inference API
      • Inference Essentials
      • AI Models
  • 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
  • Heroku Architecture
  • Stacks (operating system images)
  • Upgrading to the Latest Stack

Upgrading to the Latest Stack

English — 日本語に切り替える

Last updated May 01, 2025

Table of Contents

  • Introduction
  • General Upgrading Strategy
  • Testing an App on a New Stack
  • Upgrading an App
  • Rolling Back
  • Common Issues

This page is not applicable to Fir apps. You can’t change the stack on Fir apps from cnb. You can upgrade the base image used on Fir apps via project.toml when a new base image, like heroku/heroku:26, becomes available in the future.

 

The Heroku-20 stack reached end-of-life on April 30th, 2025. Upgrade to a newer stack as soon as possible. See the Heroku-20 End-Of-Life FAQ for more details.

Introduction

This article describes how to upgrade your app to use the latest Heroku stack. Refer to the Stacks article to understand what a stack is, which stacks are available, and how to determine the stack your application is currently using.

When a Heroku app is built, the source code for your application, together with the fetched dependencies and output of the build such as the language and framework, are assembled into a bundle known as a slug. This slug will typically only be compatible with the stack on which it was built, so apps that have previously had a deploy must be rebuilt in order to be compatible with a new stack.

Changing an existing app’s stack is a very similar process to a standard app deploy. First, the stack setting of the app is updated to request a change in the target stack used for subsequent builds. Next, a new build needs to be triggered so that a new slug is created that targets/is compatible with the new stack. This new build is deployed in exactly the same way as a standard build - for example there is no downtime for the stack upgrade to occur, and rollbacks can be performed in the same way.

General Upgrading Strategy

After determining what stack your application is currently using, you must decide which stack to migrate to. In general, you should always move to the very latest available stack.

You should first review the changes between the stack you’re currently running, and the intended destination stack, as well as their respective recommendations for upgrades from an earlier stack. The Stacks article contains a list of all stacks, and the detail page for each stack linked therein contains upgrading notes.

When upgrading more than one stack generation, e.g. from Heroku-20 to Heroku-24, remember to review the upgrade notes for all intermediate stack generations to gain a comprehensive understanding of the all the changes involved.

Before upgrading your production app to a new stack, it is highly recommended you either create a test app with the new stack first (detailed in the next section), or try the upgrade with an existing staging or development app first.

Testing an App on a New Stack

You may either use a Review App to create a temporary version of your app on the desired stack, or manually create a new app that uses the desired stack and deploy your code to it.

Review Apps (Recommended)

If your organization uses Review Apps, we recommend testing a new stack by creating a branch that changes the stack definition in app.json as follows:

{
   "stack": "heroku-24"
}

Pushing this branch and creating a Pull Request for it will then deploy the app on the new stack as a Review App, where it can be thoroughly tested.

Manually Created Test App

You may also test your codebase on a different stack by creating a new test app from an existing application.

Creating a New Test App

From an existing app’s codebase, run heroku create with arguments that create a separate test app under a different name and Git remote:

$ heroku create --remote heroku-24 --stack heroku-24 <your app name>-heroku-24

This command will:

  • Create a new app named “<your app name>-heroku-24”;
  • Set the base image to the Heroku-24 stack for that newly created app;
  • Set up a new Git remote named “heroku-24”.

Your Git repository now contains at least two remotes: heroku, pointing to your existing production app, and heroku-24, pointing to the new app you just created. Pushing changes to one of these apps will not impact the respective other app.

Migrating Add-ons and Config Vars

In order for your app to be fully functional, you must also mirror any add-ons and config vars.

To list your existing app’s add-ons, run:

$ heroku addons --remote heroku

For each of the add-ons listed, create a corresponding counterpart on your test app:

$ heroku addons:create --remote heroku-24 <add-on>

Next, examine your existing app’s config vars, as well as the new app’s config vars that were already set by any add-ons you may have provisioned:

$ heroku config --shell --remote heroku
…
$ heroku config --shell --remote heroku-24
…

For any config var present on your existing app that isn’t yet set on your test app, set it on the test app:

$ heroku config:set --remote heroku-24 <name>=<value>

The --shell option of heroku config outputs variables in a format that you can easily copy, and then paste into a heroku config:set command line.

Deploying the Test App

Deploying your new app will not affect your currently running app.

Push the source to the test app’s remote:

$ git push heroku-24 main
Counting objects: 67, done.
...
-----> Ruby app detected
-----> Compiling Ruby/Rack
...

Once the app is deployed, you should verify that it is working correctly, and if not, make any required changes. If you encounter issues not covered in the stack upgrade notes for that stack version and need assistance, open a support ticket with the stack name in the subject line.

$ heroku open --remote heroku-24
$ heroku logs --remote heroku-24

Removing the Test App

After you have finished verifying that the test app works correctly, you can remove it like so:

$ heroku apps:destroy --remote heroku-24

Upgrading an App

Setting the Stack

To upgrade via the Heroku CLI, use the stack:set command on your production app:

$ heroku stack:set heroku-24 -a <app name>
Setting stack to heroku-24... done
You will need to redeploy ⬢ <app-name> for the change to take effect.
Run git push heroku main to trigger a new build on ⬢ <app-name>.

For apps that have previously been built, this does not immediately change the stack of the app - a new build is required (which will target the chosen stack) for the change to take effect. For apps where code has never been deployed (such as add-on only apps), the stack change will take immediate effect and so for them a new deploy is not required.

If you have no changes to your source pending release, you can create an empty commit with no changes, to trigger a new build:

$ git commit --allow-empty -m "Upgrading to heroku-24"
[main 973c3f7] Upgrading to heroku-24

To create the new release, push to your production app:

$ git push heroku main

Your production app is now running on the latest stack, and you should verify that everything is working as expected.

Updating app.json

If you are using app.json, you should also specify the stack there to ensure that your Review Apps and Heroku CI runs use the same stack:

{
   "stack": "heroku-24"
}

An existing app’s stack cannot be changed using app.json. The stack specified is only applied to newly created apps that are a Review App, a Heroku CI test run app, or an app created using a Heroku Buttons.

Pipeline Promotions

When using the Heroku Pipelines feature, promoting an app copies its slug to the target app and overwrites the target app’s stack to match the stack of the originating app. As such there is no need to use stack:set on the downstream (production) app directly. Instead, upgrade the stack of the staging app, verify the app is running as expected, and then perform a pipeline promotion as normal.

Upgrading via Dashboard

To upgrade via the Heroku Dashboard, navigate to your app settings page and click the Upgrade Stack button. Confirm that you want to upgrade, which will set the stack to the latest version.

The Upgrade Stack button is only shown if you have sufficient permissions to update the stack on the app.

For apps that have previously been built, you will see that the stack upgrade is pending; the upgrade will take effect on the next deploy. For apps where code has never been deployed (such as add-on only apps), the stack change will take immediate effect and so for them a new deploy is not required.

Rolling Back

If your app isn’t working after you changed the stack and deployed a change, you can roll back to a previous release. Rolling back to a previous release quickly restores functionality until resolve the issue by debugging or contact support.

First you need the release version of the last release that was using the previous stack. In the example v13 was the deploy after the stack change:

$ heroku releases
=== production-app Releases
v13  Deploy 973c3f7                  joe@example.com   2024/06/12 10:55:16
v12  Deploy ddb317d                  jill@example.com  2024/06/09 15:33:59
...

Then roll back to the previous working release. In the example, that’s v12:

$ heroku rollback v12

Your production app is now again running on the previous stack.

Alternatively, if you would prefer not to use the rollback feature, you can change the stack back using heroku stack:set <original-stack-name> and then complete the stack downgrade by performing another deploy.

Common Issues

Old Buildpack Versions

The buildpacks defined for an app can be specified using several different forms of buildpack reference. Pinning to a specific buildpack version tag/branch/SHA will mean any compatibility fixes for new stacks won’t be picked up automatically, which may cause the build to fail on newer stacks.

List the current buildpacks using:

$ heroku buildpacks

If you see any buildpack URLs ending with a # followed by a Git reference (e.g. a commit SHA, branch name or tag name), these should be be replaced with a buildpack URL that does not contain the version suffix. See buildpack references for more details.

Third-Party Buildpacks

We expect most third-party buildpacks will work with a new stack. If your app is using a third-party buildpack, and you experience an issue building your app, we recommend clearing the build cache:

$ heroku plugins:install @heroku-cli/heroku-builds
$ heroku builds:cache:purge

If clearing the build cache doesn’t work, we suggest opening up an issue on the buildpack’s GitHub repository.

EOL Ruby version

Applications using older versions of Ruby must migrate to a supported Ruby version when upgrading their stack image. For suggestions to ease this process see Migrating Your Ruby Apps to the Latest Stack.

Stack-Specific Issues

See the “What’s new” and “Upgrade notes” sections on each stack’s detail page, for commonly encountered issues that are specific to that stack:

  • Heroku-22
  • Heroku-24

Keep reading

  • Stacks (operating system images)

Feedback

Log in to submit feedback.

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