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
  • Extending Heroku
  • Building Add-ons
  • Add-on Guidelines & Requirements
  • Add-on Partner Technical Best Practices

Add-on Partner Technical Best Practices

English — 日本語に切り替える

Last updated February 18, 2025

Table of Contents

  • Handling plan changes should be idempotent
  • Don’t perform expensive provisions or plan changes in real time
  • Use the add-on resource UUID instead of older identifiers
  • Add-on config vars should be relevant to the application
  • Use the correct email address for customers
  • Identifying users sent through SSO
  • App names are mutable
  • Attachable add-ons can be attached to multiple apps
  • Add-on slugs and plan slugs cannot change
  • Questions and suggestions

This list of technical best practices provides guidance on how to handle common scenarios that you might encounter when building an add-on integration. More documentation about building add-ons is available in the Building Add-ons section of Dev Center.

Handling plan changes should be idempotent

When a request is made to upgrade or downgrade to the same plan that the add-on is already using, it should be treated as a no-op. Return a 200 OK response status code and log it on your side. If this happens often, it might represent a problem with the initial plan change that causes Heroku to believe the action was unsuccessful and so the user is retrying the action. Monitoring for this situation and treating a request to change to the same plan as idempotent is the best approach.

Don’t perform expensive provisions or plan changes in real time

If your provision will take more than a few seconds, use the Async Partner API. If your plan change will take more than a few seconds your service should respond with a 202 Accepted status code. Use the callback APIs to make any necessary changes to the ENV vars when your service has finished. See the Add-on Partner API overview for more information.

Use the add-on resource UUID instead of older identifiers

Use the resource UUID as the primary key in your apps. Older identifiers such as the Heroku ID (or HID) exist for backwards compatibility and should not be used.

The only immutable, or unchanging, identifier that we support is the resource UUID, which is the uuid field on the provision request and the resource.uuid field on the Get App Info API response.

Add-on config vars should be relevant to the application

Only set config vars that will be useful to an application at runtime and for appropriate client libraries or tools. For example, it might be appropriate to set the username/password for a service such as SMTP. However, you shouldn’t set the username/password for a dashboard (this should be handled by SSO).

Use as few config vars as possible. If all metadata is naturally expressed as a URI, use that URI. For example, DATABASE_URL instead of DATABASE_USER, DATABASE_HOST, and DATABASE_PASS.

Use the correct email address for customers

Please fetch an app owner or collaborator’s email address every time you want to send the customer an email. Customers are allowed to change this email address and the owner of an app can change, so we recommend you do not persist it in your system.

If you are on the current (V3) integration, you can follow the Syncing user access as an ecosystem partner guide.

Do not use the id key of the provision request as an email address. It will look like app123@heroku.com. This is a legacy identifier called a Heroku ID (or HID) that we maintain for backwards compatibility. It does not function as an email address.

Identifying users sent through SSO

Follow the documentation for SSO to determine the user accessing your dashboard via SSO.

Note that the user email address provided in the SSO request may not be the app owner’s email address. We support multiple collaborators on apps, and Heroku Enterprise has several roles in an organization which may have access to an app’s add-ons.

Some users will have multiple apps, each with your add-on. Some partners attempt to merge multiple installations because they share an email address. However, apps can be transferred to other accounts, and so we recommend against doing that.

App names are mutable

App names change. Users can rename apps. Whenever you need the billing app name for an add-on, we recommend you use the Get App Info API to fetch it. Note that in the future we may allow add-ons to be moved between apps at a user’s request. It is best not to tie an add-on record to the Heroku app or its name on your side.

Attachable add-ons can be attached to multiple apps

Be careful not to assume in your code that an add-on only has one Heroku app attached to it. In particular, do not use the app name from the Get App Info API as an identifier for the add-on. This results in a brittle design and will prevent you from implementing attachable add-ons or many-per-app add-ons. Instead, you should always refer to the add-on resource UUID returned by the provision request and the Get App Info API rather than the app in your code.

Add-on slugs and plan slugs cannot change

For data consistency, especially across billing, we do not allow changes to the add-on slug or plan slugs. Instead, the recommended process is to archive the existing plan by hiding it or disabling it and creating a new plan with the preferred name.

Questions and suggestions

If you have any questions or suggestions for best practices that should be included in this article, please contact us by opening a support ticket.

Keep reading

  • Add-on Guidelines & Requirements

Feedback

Log in to submit feedback.

The Add-on Ownership Model and User Authentication Guidelines for Add-on Partners Add-on Performance Expectations

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