Wilson Mar bio photo

Wilson Mar


Calendar YouTube Github


Start using Heroku with a Postgres database and integrate it with Salesforce

US (English)   Norsk (Norwegian)   Español (Spanish)   Français (French)   Deutsch (German)   Italiano   Português   Estonian   اَلْعَرَبِيَّةُ (Egypt Arabic)   Napali   中文 (简体) Chinese (Simplified)   日本語 Japanese   한국어 Korean


The marketing home page for Heroku is at

Salesforce bought Heroku some time ago.

Why Heroku

Heroku provides (up to 5) free personal app websites for developers and provides a easy way to bring GitHub repositories to the public cloud. Heroku automatically scales apps running on its platform.

Heroku can be setup to automatically deploy apps to a public web server whenever there is a Git push or pull request.

Get started with Heroku

  1. Click this URL to register for an account:

    PROTIP: If you’re creating an account on behalf of an organization, use a service account rather than using your own account.

  2. Note: To install Heroku add-ons your account must be verified.

    Toolbelt CLI Install

  3. Install https://toolbelt.heroku.com/

    brew install -g heroku-toolbelt

    The response:

    ==> Downloading https://s3.amazonaws.com/assets.heroku.com/heroku-client/heroku-
    ######################################################################## 100.0%
    Initialized empty Git repository in /private/tmp/heroku-20160722-78693-1njp97z/heroku-client/.git/
    Error: The `brew link` step did not complete successfully
    The formula built, but is not symlinked into /usr/local
    Could not symlink bin/heroku
    Target /usr/local/bin/heroku
    already exists. You may want to remove it:
      rm '/usr/local/bin/heroku'
    To force the link and overwrite all conflicting files:
      brew link --overwrite heroku
    To list all files that would be deleted:
      brew link --overwrite --dry-run heroku
    Possible conflicting files are:
    /usr/local/bin/heroku -> /usr/local/heroku/bin/heroku
    ==> Summary
    🍺  /usr/local/Cellar/heroku/3.43.5: 992 files, 6.2M, built in 7 seconds
  4. If you get the message:

    Error: The `brew link` step did not complete successfully
    The formula built, but is not symlinked into /usr/local

    Fix it by first:

    brew link --overwrite --dry-run heroku

    To force the link and overwrite all conflicting files:

    brew link --overwrite heroku

    Verify installation

  5. Open a new Terminal window

  6. Create a new Terminal window:

    heroku login

    The response:

    heroku-cli: Installing CLI... 20.22MB/20.22MB
    Enter your Heroku credentials.
  7. Enter your Heroku password.

    BTW, I like using 1Password to securely store and retrieve passwords.

  8. Enter the password

    Password (typing will be hidden):

    If you got it right, you see a message such as:

    Logged in as wilsonmar@gmail.com

    QUESTION: Where was that installed?

    PROTIP: On a Mac, the installer creates folder:*


    TODO: Set password for auto login.

New Instance

A new instance can be created using either on Heroku on-line (shown in this section) or in a shell script.

  1. Create a new instance:

    cd ~/myapp
    heroku create
  2. Go to your Dashboard Settings to delete any instances you’re not using.

    PROTIP: Like Salesforce test orgs, Heroku stay free for years if you keep to 5 apps or less.

  3. To kick off deployment from GitHub, click a Heroku Button or its URL:



    The link above deploys the sample “Phone Change” app described in the Salesforce Trailhead module: Quick Start: Heroku Connect [30 mins] to sync data between a Salesforce org and a Heroku Postgres database. The author, James Ward is Director, Open Source and Engineering Engagement at Salesforce.

  4. Field App Name can be left blank because Heroku generates a unique one such as “shielded-harbor-5440”. Type in a custom domain name if you own one from GoDaddy, etc.

  5. Select United States as the Region
  6. See https://devcenter.heroku.com/articles/pipelines
  7. Click Deploy App.

Script to create new instance

Instead of the manual approach, use my Bash script to do the equivalent of the above. It’s at:


  1. Install heroku CLI per https://devcenter.heroku.com/articles/heroku-cli

    PROTIP: The source for it is at https://github.com/heroku

  2. Create in your account Home folder a file containing the HEROKU_API_KEY pair.

    That file is run by the script that runs Heroku.

    Here a description of its actions

  3. Make and cd to a folder to hold the repo.
  4. Optionally, go to an established repo containing Node web.js and package.json


    Notice in app.json vars named “PGSSLMODE” is specified for Heroku.

    package.json contains the metadata of the application name, version, the version of dependencies, and the version of NodeJs and main file under the public folder.

    package-lock.json is created by the command “npm install”.*

  5. Clone the repository to get it local

    git clone https://github.com/jamesward/heroku-connect-phone-change --depth=1
    cd heroku-connect-phone-change

    There is also https://github.com/jamesward/heroku_hello_world

    These are the minimal files in https://github.com/jamesward/heroku-connect-phone-change or https://github.com/jamesward/heroku_hello_world

    • Procfile
    • package-lock.json
    • package.json
    • web.js or server.js - the Node application code.

    Script code to create them:

    echo "web: node server.js" > Procfile
    echo "node_modules" > .gitignore
  6. Create app in Heroku:

    heroku create  # or add $APP_NAME

    The response contains the package name and location:

    Creating app... done, ⬢ guarded-ridge-66528
    https://guarded-ridge-66528.herokuapp.com/ | https://git.heroku.com/guarded-ridge-66528.git
  7. For SSL configuration (which requires an upgrade to paid dynos), see https://devcenter.heroku.com/articles/git#prerequisites-install-git-and-the-heroku-cli

  8. Make use of the generated Git URL:

    heroku git:remote -a 


    git remote add heroku https://git.heroku.com/evening-refuge-98240.git
    git push heroku master

    The response:

    Counting objects: 58, done.
    Delta compression using up to 8 threads.
    Compressing objects: 100% (35/35), done.
    Writing objects: 100% (58/58), 545.91 KiB | 60.66 MiB/s, done.
    Total 58 (delta 21), reused 58 (delta 21)
    remote: Compressing source files... done.
    remote: Building source:
    remote: -----> Node.js app detected
    remote: -----> Creating runtime environment
    remote:        NPM_CONFIG_LOGLEVEL=error
    remote:        NODE_VERBOSE=false
    remote:        NODE_ENV=production
    remote:        NODE_MODULES_CACHE=true
    remote: -----> Installing binaries
    remote:        engines.node (package.json):  0.12.7
    remote:        engines.npm (package.json):   unspecified (use default)
    remote:        Resolving node version 0.12.7...
    remote:        Downloading and installing node 0.12.7...
    remote:        Using default npm version: 2.11.3
    remote: -----> Restoring cache
    remote:        Skipping cache restore (not-found)
    remote: -----> Building dependencies
    remote:        Installing node modules (package.json)
    remote:        body-parser@1.18.3 node_modules/body-parser
    remote:        ├── content-type@1.0.4
    remote:        ├── bytes@3.0.0
    remote:        ├── depd@1.1.2
    remote:        ├── on-finished@2.3.0 (ee-first@1.1.1)
    remote:        ├── raw-body@2.3.3 (unpipe@1.0.0)
    remote:        ├── http-errors@1.6.3 (setprototypeof@1.1.0, inherits@2.0.3, statuses@1.5.0)
    remote:        ├── qs@6.5.2
    remote:        ├── debug@2.6.9 (ms@2.0.0)
    remote:        ├── type-is@1.6.16 (media-typer@0.3.0, mime-types@2.1.19)
    remote:        └── iconv-lite@0.4.23 (safer-buffer@2.1.2)
    remote:        express@4.16.3 node_modules/express
    remote:        ├── escape-html@1.0.3
    remote:        ├── array-flatten@1.1.1
    remote:        ├── setprototypeof@1.1.0
    remote:        ├── content-type@1.0.4
    remote:        ├── cookie-signature@1.0.6
    remote:        ├── utils-merge@1.0.1
    remote:        ├── merge-descriptors@1.0.1
    remote:        ├── methods@1.1.2
    remote:        ├── path-to-regexp@0.1.7
    remote:        ├── range-parser@1.2.0
    remote:        ├── encodeurl@1.0.2
    remote:        ├── vary@1.1.2
    remote:        ├── parseurl@1.3.2
    remote:        ├── fresh@0.5.2
    remote:        ├── etag@1.8.1
    remote:        ├── statuses@1.4.0
    remote:        ├── cookie@0.3.1
    remote:        ├── content-disposition@0.5.2
    remote:        ├── serve-static@1.13.2
    remote:        ├── safe-buffer@5.1.1
    remote:        ├── depd@1.1.2
    remote:        ├── on-finished@2.3.0 (ee-first@1.1.1)
    remote:        ├── finalhandler@1.1.1 (unpipe@1.0.0)
    remote:        ├── debug@2.6.9 (ms@2.0.0)
    remote:        ├── qs@6.5.1
    remote:        ├── proxy-addr@2.0.4 (forwarded@0.1.2, ipaddr.js@1.8.0)
    remote:        ├── send@0.16.2 (ms@2.0.0, destroy@1.0.4, mime@1.4.1, http-errors@1.6.3)
    remote:        ├── type-is@1.6.16 (media-typer@0.3.0, mime-types@2.1.19)
    remote:        ├── accepts@1.3.5 (negotiator@0.6.1, mime-types@2.1.19)
    remote:        └── body-parser@1.18.2 (bytes@3.0.0, http-errors@1.6.3, raw-body@2.3.2, iconv-lite@0.4.19)
    remote:        pg@4.5.7 node_modules/pg
    remote:        ├── packet-reader@0.2.0
    remote:        ├── js-string-escape@1.0.1
    remote:        ├── pg-connection-string@0.1.3
    remote:        ├── buffer-writer@1.0.1
    remote:        ├── generic-pool@2.4.2
    remote:        ├── semver@4.3.6
    remote:        ├── pgpass@0.0.3 (split@0.3.3)
    remote:        └── pg-types@1.13.0 (pg-int8@1.0.1, postgres-bytea@1.0.0, postgres-date@1.0.3, postgres-array@1.0.2, postgres-interval@1.1.2)
    remote: -----> Caching build
    remote:        Clearing previous node cache
    remote:        Saving 2 cacheDirectories (default):
    remote:        - node_modules
    remote:        - bower_components (nothing to cache)
    remote: -----> Pruning devDependencies
    remote: -----> Build succeeded!
    remote: -----> Discovering process types
    remote:        Procfile declares types     -> (none)
    remote:        Default types for buildpack -> web
    remote: -----> Compressing...
    remote:        Done: 11.2M
    remote: -----> Launching...
    remote:        Released v3
    remote:        https://guarded-ridge-66528.herokuapp.com/ deployed to Heroku
    remote: Verifying deploy... done.
    To https://git.heroku.com/guarded-ridge-66528.git
            * [new branch]      master -> master
  9. Instantiate 1 app server instance:

    heroku ps:scale web=1

    Expected response:

    Scaling dynos... done, now running web at 1:Free
  10. Open the app’s web page in your default browser:

    heroku open

    A sample URL:


Add-on Postgres database

To add databases, monitoring services, caching services, and queuing systems, See https://elements.heroku.com/addons Now you are going to deploy an add-on. Heroku add-ons are cloud services,

Provision a relational database by adding the Heroku Postgres add-on described at https://elements.heroku.com/addons/heroku-postgresql

  1. In the Heroku Dashboard, click the “Manage App” button to visit the Heroku Dashboard
  2. Click on your new application name (for example, guarded-ridge-66528).
  3. Click the Resources tab.
  4. In the Add-ons section search field, type “Heroku Postgres” and click the response of same name.
  5. Assume the plan in the pop-up (“Hobby Dev - Free”) then click Provision.

    “The addon heroku-postgresql has been installed. Check out the documentation in its Dev Center article to get started.”

    NOTE: The simplicity and speed of this process belies the complexity of what just happened: You provisioned one of Heroku’s 150+ add-on services. In this case, it’s a relational database. The service is fully managed, is already running, and is now connected to your application.

    Heroku typically connects a provisioned add-on to an application by setting a configuration variable that is available as a runtime environment variable within the application.

  6. Select the Settings tab.
  7. In the “Config Vars” section, click Reveal Config Vars (Key/Value pairs):

    • DATABASE_URL = postgres://abcdvnhzwoskmf:9310494d102ba4df7de3b3fe33921de3410228045309e28ae5f98411e01033c0@ec2-184-73-199-189.compute-1.amazonaws.com:5432/det6u4itvvuivx

    • PGSSLMODE = “require”, which Heroku should have taken from the app.json file:

      "env": {
     "PGSSLMODE": {
       "description": "Require SSL for Postgres",
       "value": "require"

    QUESTION: What is the version of Postgres?

    Set Up Trailhead Playground

  8. From the bottom of a Trailhead module page, select your “Trailhead Playground” and click Launch.


    PROTIP: If you time out, close that screen, then return to the Trailhead Module page to login using your Salesforce Trailhead login, then Launch again.

    This should open to a “Bolt Solutions” app.

  9. Follow the instructions in Get Your Trailhead Playground Username and Password unit of the Trailhead Playground Management module. You’ll need your username and password to provision your Heroku Connect Add-on.

    Add a new field to the Contact object:

  10. With the Lightning UX, click the wheel to select “Setup” for a new browser window at the Setup app.
  11. Click the Object Manager tab next to “Home”.
  12. Click the blue Contact under LABEL.
  13. Click Fields & Relationships.
  14. Click New.
  15. For Data Type, scroll down to select Text, then scroll up to click Next.

    Complete the New Custom Field:

  16. Field Label: “External Phone ID”
  17. Length: 10
  18. Field Name: External_Phone_ID
  19. Check “Always require a value in this field in order to save a record”
  20. Unique: Select “Do not allow duplicate values” Leave auto selection of “Treat “ABC” and “abc” as duplicate values (case insensitive)”
  21. External ID: Check “Set this field as the unique record identifier from an external system”
  22. Click Next.
  23. Check “Visible” at the heading to make the field visible to all profiles.
  24. Scroll down to click Next,
  25. Click Save.

    Notice API Name is “External_Phone_ID__c”.

    We’re done with Salesforce for a while, but keep the tab handy.

    Add-On Heroku Connect

    Applications running on Heroku can use a number of different methods to integrate with Salesforce data, including Salesforce REST APIs. But an easier approach is to use the Heroku Connect add-on, which provides bi-directional synchronization between Salesforce and Heroku Postgres, allowing you to unify and share the data in a Heroku Postgres SQL database with the contacts, accounts, and other custom objects in a Salesforce database.

  26. Go back to the Heroku Dashboard, then find your application and click the management console.
  27. Click the Resources tab.
  28. In the Add-ons section search field, type “Heroku Connect” and click the response of same name.
  29. In the pop-up, select the plan (“Demo Edition - Free”) then click Provision for this message:

    “The addon herokuconnect has been installed. Check out the documentation in its Dev Center article to get started.””

    Create Connection on Heroku

  30. Click “Heroku Connect” under the “Add-ons” section label for a new window.
  31. Click “Setup Connection”.

    Heroku Connect locates the Heroku Postgres database “salesforce” provisioned earlier.

  32. Click Next.

    Leave default “Production” Environment (not Sandbox nor Custom Domain).

  33. Click Authorize.
  34. If you’re prompted, Login again with your Trailhead Playground credentials, then click “Allow”.

    Set up Heroku Connect

    Create a mapping between the Contact object in Salesforce and a table in the Heroku Postgres database.

    TODO: Image here.

  35. In Heroku, click “Mappings” tab.
  36. Click “+ Create Mapping” button near the bottom-right.
  37. Press command+F to find “Contact”, then click on it.
  38. Under the “Database -> Salesforce” section, check “Write database updates to Salesforce using – None – as the unique identifier”
  39. option and choose “External_Phone_ID__c” from the dropdown list

    BLAH: Stuck here. “External_Phone_ID__c” NOT in the dropdown list for Trailhead module Quick Start: Heroku Connect


    This forum post mentions

    ”– Add a new ‘Phone UUID’ custom field on the User standard object with the resulting API name of ‘Phone_UUID__c’. The field should be of type ‘Text’ and marked as ‘Unique’ and ‘External ID’

    “Can you explain how to “Update any existing User record in your Developer Edition instance to have a value of ‘0000123442’ for the ‘Phone_UUID__c’ field.” I think this is what is tripping me up and causing me to get the following error message:

  40. In the Mapped Fields section, select the following fields:

    • Created Date (already checked)
    • Email
    • FirstName
    • HomePhone
    • LastName and check Index
    • MobilePhone
    • Name (already checked)
    • Phone

    • QUESTION: Where’s External phone ???
  41. Click Save.

    When you’ve completed the mapping setup, the data begins synchronizing. Mapping Complete Your application is now syncing (bidirectionally) a subset of the Contact object in Salesforce with a new table in the Heroku Postgres database associated with your app.

  42. When the syncing is complete, open your Heroku app in a new browser tab, by entering

    http://APP_NAME.herokuapp.com (replacing APP_Name with your app name)

    On the app

  43. Complete the form to change a contact’s phone number using the following values, which changes an existing record in the sample database:

    • First Name: Tim
    • Last Name: Barr
    • Email: barr_tim@grandhotels.com
    • Phone: (415) 555-1212
  44. Click “Update Phone Number” for the “Record updated!” message.

    This should update the contact record in the Heroku Postgres database and be synced with Salesforce via Heroku Connect. So verify the updates in your Trailhead Playground:

    (Syncing could take a few minutes so ensure your Trailhead Playground is updated.)

  45. In Salesforce Lightning UX, click the App Launcher icon and select the Sales app.
  46. Click the Contacts tab.
  47. Click Recently Viewed to select All Contacts.
  48. Scroll down to click Tim Barr, then click the Details tab and see that the Phone was changed from “(312) 596-1000”.

Integrating Node Applications with GitHub [1h 43m] 5 Aug 2016 by Daniel Stern covers deploying GitHub branches automatically with cloud-based deployment software Heroku, from acount sign-up to …

Other Trailhead Modules to Learn

Heroku Enterprise Basics [1 hr 10 mins] Learn the basics of how and when to use the Heroku Enterprise platform.

Salesforce & Heroku Integration [2 hrs] Learn patterns and methodology of integrating apps on Heroku with Salesforce.

Heroku Flow [1 hr] to manage continuous delivery in app development

Java App Development on Heroku [1 hr] Deploy production Java apps on Heroku.

Apex Integration Services [2 hrs] +1600

Other Topics

Heroku Shield

Heroku Agile Accelerator from AppExchange Trello

https://github.com/jamesward/heroku-buildpack-static Heroku buildpack for handling static sites and single page web apps


https://github.com/jamesward/atom-heroku-tools Stores a Heroku API Access Token the user’s .netrc file


https://www.cncf.io/community/recorded-events/ http://bit.ly/2MpdYIk VIDEO: Setting up the Heroku git-push workflow on your Kubernetes cluster in 60 seconds with Gitkube https://www.cncf.io/wp-content/uploads/2018/06/Gitkube-CNCF-webinar-June-26-1.pdf

https://github.com/financialforcedev/orizuru Streamlined communication between Heroku dynos / other worker processes It leverages Apache Avro for schema validation and communication.


https://thoughtbot.com/upcase/videos/heroku-tips-and-tricks video [subscription]

http://resources.docs.salesforce.com/rel1/doc/en-us/static/pdf/SF_Git_cheatsheet_web.pdf Git CheatSheet for Working with Private Spaces in Heroku dynos


https://cloud.google.com/cloud-build/ https://github.com/apps/google-cloud-build Google Cloud offers the first 120 build minutes per day free

More about Salesforce

This is one of a series about Salesforce

  1. Salesforce index

  2. Salesforce Ohana (about the Salesforce company, offices, mascots, emojis, and store)
  3. Salesforce Glossary (of acronyms)
  4. Salesforce Events (Conferences, local Meetups, ) to meet people face-to-face
  5. Salesforce Exhibitors (at Dreamforce)
  6. Salesforce Onboarding (Trailhead and IDEs)
  7. Salesforce Rock Stars (and influencers)

  8. Salesforce Offerings (Clouds, Industries, Domains, GitHub, editions, pricing, features, versions)
  9. Salesforce Certifications (training and exams)
  10. Salesforce Projects, Superbadges, and Sample Apps
  11. Salesforce myTrailhead for custom Trailhead content

  12. Salesforce Project Plans
  13. Salesforce Jobs (within Salesforce, with partners, etc.)
  14. Salesforce User Roles and Personas

  15. Salesforce Apps (in AppExchange)
  16. Salesforce Alexa
  17. Salesforce Heroku (external apps)
  18. Salesforce DX (Developer eXperience)

  19. Salesforce Non-Profit support
  20. Salesforce NPSP (Non-Profit Success Pack) performance (with Gatling)

  21. Salesforce Data Management
  22. Salesforce Einstein
  23. Salesforce Selenium (test automation)