Getting Started on Heroku with Node.js | Heroku Dev Center (2024)

Introduction

This tutorial can help you deploy a Node.js app to Heroku in minutes.

The tutorial assumes that you have:

  • A verified Heroku Account
  • Node.js and npm installed locally
  • An Eco dynos plan subscription (recommended)

Using dynos to complete this tutorial counts towards your usage. To complete this tutorial, we recommend using our low-cost plans. Eligible students can apply for platform credits through our new Heroku for GitHub Students program.

Set Up

The Heroku CLI requires Git, the popular version control system. If you don’t have Git installed, complete these tasks before proceeding.

In this step you install the Heroku Command Line Interface (CLI). You use the CLI to manage and scale your applications, provision add-ons, view your application logs, and run your application locally.

Download and run the installer for your platform.

Getting Started on Heroku with Node.js | Heroku Dev Center (1)macOS

$ brew tap heroku/brew && brew install heroku

Getting Started on Heroku with Node.js | Heroku Dev Center (2)Windows

Download the appropriate installer for your Windows installation:

64-bit installer

32-bit installer

More installation options for the Heroku Command Line Interface (CLI) can be found here.

When installation completes, you can use the heroku command from your terminal.

On Windows, start the Command Prompt (cmd.exe) or Powershell to access the command shell.

To log in to the Heroku CLI, use the heroku login command.

$ heroku loginheroku: Press any key to open up the browser to login or q to exit › Warning: If browser does not open, visit › https://cli-auth.heroku.com/auth/browser/***heroku: Waiting for login...Logging in... doneLogged in as me@example.com

This command opens your web browser to the Heroku login page. If your browser is already logged in to Heroku, click the Log in button.

This authentication is required for the heroku and git commands to work correctly.

If you’re behind a firewall that requires use of a proxy to connect with external HTTP/HTTPS services, you can set the HTTP_PROXY or HTTPS_PROXY environment variables in your local development environment before running the heroku command.

Before you continue, check that you have the prerequisites installed properly. Type each command below, and make sure that each one displays the version that you installed. (Your versions can be different from the example.) If no version is returned, install the prerequisites.

To declare app dependencies and subsequent steps, you must complete this local setup.

This tutorial works for any version of Node greater than 18.

$ node --versionv20.9.0

npm is installed with Node, so check that it’s there. If you don’t have it, install a more recent version of Node.

$ npm --version10.1.0

Now check that you have git installed. If not, install it, and test again.

$ git --versiongit version 2.42.0

Prepare the App

In this step, you prepare a sample application that’s ready to be deployed to Heroku.

If you’re new to Heroku, we recommend that you complete this tutorial using the Heroku-provided sample application.

However, if you have an existing application that you want to deploy instead, read this article to learn how to prepare it for Heroku deployment.

To clone a local version of the sample application that you can then deploy to Heroku, execute these commands in your local command shell or terminal.

$ git clone https://github.com/heroku/node-js-getting-started.git$ cd node-js-getting-started

You now have a functioning Git repository that contains a simple application and a package.json file, which Node’s dependency manager uses.

Deploy the app

In this step, you deploy the app to Heroku.

Using dynos to complete this tutorial counts towards your usage. To control costs, Delete your app as soon as you‘re done.

By default, apps use Eco dynos if you’re subscribed to Eco. Otherwise, it defaults to Basic dynos. If you plan to deploy many small apps to Heroku, we recommend the Eco dynos plan, which is shared across all Eco dynos in your account. Learn more here. Eligible students can apply for platform credits through our Heroku for GitHub Students program.

Create an app on Heroku, which prepares Heroku to receive your source code.

$ heroku createCreating app... done, ⬢ shrouded-anchorage-35377https://shrouded-anchorage-35377.herokuapp.com/ | https://git.heroku.com/shrouded-anchorage-35377.git

When you create an app, you also create a Git remote called heroku. It’s associated with your local Git repository.

Heroku generates a random name for your app, in this case shrouded-anchorage-35377. Or you can pass a parameter to specify your own app name.

Deploy your code.

$ git push heroku mainEnumerating objects: 554, done.Counting objects: 100% (554/554), done.Delta compression using up to 20 threadsCompressing objects: 100% (412/412), done.Writing objects: 100% (554/554), 248.74 KiB | 124.37 MiB/s, done.Total 554 (delta 109), reused 548 (delta 106), pack-reused 0remote: Compressing source files... done.remote: Building source:remote:remote: -----> Building on the Heroku-22 stackremote: -----> Determining which buildpack to use for this appremote: -----> Node.js app detectedremote:remote: -----> Creating runtime environmentremote:remote: NPM_CONFIG_LOGLEVEL=errorremote: NODE_VERBOSE=falseremote: NODE_ENV=productionremote: NODE_MODULES_CACHE=trueremote:remote: -----> Installing binariesremote: engines.node (package.json): 20.xremote: engines.npm (package.json): unspecified (use default)remote:remote: Resolving node version 20.x...remote: Downloading and installing node 20.9.0...remote: Using default npm version: 10.1.0remote:remote: -----> Installing dependenciesremote: Installing node modules (package.json)remote:remote: added 160 packages, and audited 161 packages in 4sremote:remote: 64 packages are looking for fundingremote: run `npm fund` for detailsremote:remote: found 0 vulnerabilitiesremote:remote: -----> Buildremote:remote: -----> Caching buildremote: - node_modulesremote:remote: -----> Pruning devDependenciesremote:remote: up to date, audited 74 packages in 450msremote:remote: 9 packages are looking for fundingremote: run `npm fund` for detailsremote:remote: found 0 vulnerabilitiesremote:remote: -----> Build succeeded!remote: -----> Discovering process typesremote: Procfile declares types -> webremote:remote: -----> Compressing...remote: Done: 43.4Mremote: -----> Launching...remote: Released v3remote: https://shrouded-anchorage-35377.herokuapp.com/ deployed to Herokuremote:remote: Verifying deploy... done.To https://git.heroku.com/shrouded-anchorage-35377.git * [new branch] main -> main

Ensure that at least one instance of the app is running.

$ heroku ps:scale web=1

Visit the app at the URL generated by its app name. As a shortcut, you can open the website.

$ heroku open

View Logs

Heroku treats logs as streams of time-ordered events aggregated from the output streams of all your app and Heroku components, providing a single channel for all of the events.

View information about your running app using one of the logging commands, heroku logs --tail:

$ heroku logs --tail2023-03-02T19:56:09.671017+00:00 heroku[web.1]: Starting process with command `npm start`2023-03-02T19:56:12.617099+00:00 app[web.1]:2023-03-02T19:56:12.617126+00:00 app[web.1]: > node-js-getting-started@0.3.0 start2023-03-02T19:56:12.617127+00:00 app[web.1]: > node index.js2023-03-02T19:56:12.617127+00:00 app[web.1]:2023-03-02T19:56:12.738203+00:00 app[web.1]: Listening on 168322023-03-02T19:56:13.217147+00:00 heroku[web.1]: State changed from starting to up

Visit your application in the browser again, and you see another log message generated.

To stop streaming the logs, press Control+C.

Define a Procfile

Use a Procfile, which is a text file in the root directory of your application, to explicitly declare what command executes to start your app.

The Procfile in the example app you deployed looks like:

web: npm start

The name web is important because it declares that this single process type attaches to Heroku’s HTTP routing stack and receives web traffic when deployed. This command uses the start script specified in the package.json.

Procfiles can contain additional process types. For example, you can declare one for a background worker process that processes items off of a queue.

Scale the App

Right now, your app runs on a single web dyno. Think of a dyno as a lightweight container that runs the command specified in the Procfile.

You can check how many dynos are running using the ps command.

$ heroku ps=== web (Eco): npm start (1)web.1: up 2023/03/02 15:56:13 -0400 (~ 6m ago)

By default, your app deploys on an Eco dyno. If they don’t receive any traffic, Eco dynos sleep after 30 minutes of inactivity. Upon waking, expect a delay of a few seconds for the first request. Subsequent requests perform normally. Eco dynos also consume from a monthly, account-level quota of Eco dyno hours. As long as the quota isn’t exhausted, all Eco apps can continue to run.

To avoid dyno sleeping, you can upgrade to a Basic or Professional dyno type as described in the Dyno Types article. For example, if you migrate your app to a professional dyno, you can scale it by running a command that tells Heroku to execute a specific number of dynos, each running your web process type.

Scaling an application on Heroku is equivalent to changing the number of dynos running. Scale the number of web dynos to zero.

$ heroku ps:scale web=0

Access the app again by hitting refresh on the web tab, or heroku open to open it in a web tab. You get an error message because you no longer have any web dynos available to serve requests.

Scale it up again.

$ heroku ps:scale web=1

Declare App Dependencies

Heroku recognizes an app as Node.js from a package.json file in the root directory. For your own apps, you can create one by running npm init --yes.

The demo app that you deployed already has a package.json that looks like:

{ "name": "node-js-getting-started", "version": "0.3.0", ... "engines": { "node": "20.x" }, "dependencies": { "ejs": "^3.1.5", "express": "^4.15.2" }, ...}

The package.json file determines the version of Node.js to run your application on Heroku and the dependencies to install with your application.

Run this command in your local directory to install the dependencies, preparing your system to run the app locally.

$ npm installadded 160 packages in 6s

After installation, a package-lock.json file is generated when npm install is run. Make sure to check this into Git. When subsequent dependencies are added, npm makes changes to this file, so make sure to add those changes to Git too.

When an app is deployed, Heroku reads the package.json to install the appropriate node version and the package-lock.json to install the dependencies.

Run the App Locally

Start your application locally using the heroku local command, which installed as part of the Heroku CLI.

$ heroku local web --port 5001[OKAY] Loaded ENV .env File as KEY=VALUE Format4:09:49 p.m. web.1 | > node-js-getting-started@0.3.0 start4:09:49 p.m. web.1 | > node index.js4:09:49 p.m. web.1 | Listening on 5001

Just like Heroku, heroku local examines the Procfile to determine what to run.

Open http://localhost:5001 with your web browser to see your app running locally.

To stop the app from running locally, in the CLI, press Ctrl+C to exit.

Push Local Changes

In this step, you learn how to propagate a local change to the application through to Heroku. As an example, you modify the application to add an additional dependency and the code to use it.

Begin by adding a dependency for cool-ascii-faces in package.json. Run this command.

$ npm install cool-ascii-facesadded 11 packages in 2s

Modify index.js so that it requires this module at the start. Also add a new route (/cool) that uses it. You want the final code to look like:

const cool = require('cool-ascii-faces')const express = require('express')const path = require('path')const PORT = process.env.PORT || 5001express() .use(express.static(path.join(__dirname, 'public'))) .set('views', path.join(__dirname, 'views')) .set('view engine', 'ejs') .get('/', (req, res) => res.render('pages/index')) .get('/cool', (req, res) => res.send(cool())) .listen(PORT, () => console.log(`Listening on ${ PORT }`))

Test locally.

$ npm install$ heroku local --port 5001

When you visit your application at http://localhost:5001/cool, the sample application shows you cute faces on each refresh: ( ⚆ _ ⚆ ).

Deploy. Almost every deploy to Heroku follows this same pattern. First, add the modified files to the local Git repository.

$ git add .

Commit the changes to the repository.

$ git commit -m "Add cool face API"

Deploy, just as you did previously.

$ git push heroku main

Check that everything works.

$ heroku open cool

If everything is in working order, you see another face.

Provision Add-Ons

Add-ons are third-party cloud services that provide out-of-the-box additional services for your application, from persistence through logging to monitoring and more.

By default, Heroku stores 1,500 lines of logs from your application. However, it makes the full log stream available as a service. Several add-on providers have logging services that provide things such as log persistence, search, and email and SMS alerts.

In this step, you provision one of these logging add-ons, Papertrail.

Provision the papertrail logging add-on.

$ heroku addons:create papertrailCreating papertrail on ⬢ shrouded-anchorage-35377... freeWelcome to Papertrail. Questions and ideas are welcome (technicalsupport@solarwinds.com). Happy logging!Created papertrail-fluffy-46630 as PAPERTRAIL_API_TOKENUse heroku addons:docs papertrail to view documentation

The add-on is now deployed and configured for your application. You can list add-ons for your app.

$ heroku addons

To see this particular add-on in action, visit your application’s Heroku URL a few times. Each visit generates more log messages, which route to the papertrail add-on. Visit the papertrail console to see the log messages.

$ heroku addons:open papertrail

Your browser opens a Papertrail web console showing the latest log events. You can search and set up alerts.

Getting Started on Heroku with Node.js | Heroku Dev Center (3)

Start a Console

To get a feel for how dynos work, you can create another one-off dyno and run the bash command, which opens a shell on that dyno. You can then execute commands there. Each dyno has its own ephemeral filespace, populated with your app and its dependencies. When the command completes, in this case bash, the dyno is removed.

$ heroku run bashRunning bash on ⬢ shrouded-anchorage-35377... up, run.1662 (Eco)~ $ lsProcfile README.md app.json index.js node_modules package-lock.json package.json public test.js views~ $ exitexit

If you receive Error connecting to process, try configuring your firewall.

To exit the shell and terminate the dyno, type exit.

Define Config Vars

With Heroku, you can externalize configuration, storing data such as encryption keys or external resource addresses in config vars.

At runtime, config vars are exposed as environment variables to the application. For example, modify index.js so that it introduces a new route, /times, that repeats an action depending on the value of the TIMES environment variable. Under the existing get() call, add another.

.get('/times', (req, res) => res.send(showTimes()))

At the end of the file, add this definition for the new function, showTimes().

function showTimes() { const times = process.env.TIMES || 5 let result = '' for (i = 0; i < times; i++) { result += i + ' ' } return result}

heroku local automatically sets up the environment based on the contents of the .env file in your local directory. In the top-level directory of your project, an .env file has these contents.

TIMES=2

If you run the app with heroku local --port 5001 and then open http://localhost:5001/times, you see two numbers generated every time.

To set the config var on Heroku, execute this command.

$ heroku config:set TIMES=2

View the config vars that are set using heroku config.

$ heroku config=== shrouded-anchorage-35377 Config VarsPAPERTRAIL_API_TOKEN: w9EnziexBT2mzMDtS4MTIMES: 2

Deploy your changed application to Heroku, and then visit it by running heroku open times.

Provision a Database

Adding a database to complete this tutorial counts towards your usage. To control costs, delete your database as soon as you’re done. Learn about our low-cost plans. Eligible students can apply for platform credits through our Heroku for GitHub Students program.

The add-on marketplace has a large number of data stores, from Redis and MongoDB providers to Postgres and MySQL. In this step, you add a Heroku Postgres Essential-0 database to your app.

Add the database.

$ heroku addons:create heroku-postgresql:essential-0Creating heroku-postgresql:essential-0 on ⬢ shrouded-anchorage-35377... ~$0.007/hour (max $5/month)Database should be available soonpostgresql-asymmetrical-00466 is being created in the background. The app will restart when complete...Use heroku addons:info postgresql-asymmetrical-00466 to check creation progressUse heroku addons:docs heroku-postgresql to view documentation

This action creates a database and sets a DATABASE_URL environment variable that you can check by running heroku config.

Use npm to add node-postgres to your dependencies.

$ npm install pgadded 14 packages in 2s
 "dependencies": { "cool-ascii-faces": "^1.3.4", "ejs": "^3.1.5", "express": "^4.15.2", "pg": "^8.11.3" },

Edit your index.js file to use this module to connect to the database specified in your DATABASE_URL environment variable. Add this code near the top.

const { Pool } = require('pg')const pool = new Pool({ connectionString: process.env.DATABASE_URL, ssl: { rejectUnauthorized: false }})

Add another route, /db, by adding this code just after the existing .get('/', ...).

.get('/db', async (req, res) => { try { const client = await pool.connect(); const result = await client.query('SELECT * FROM test_table'); const results = { 'results': (result) ? result.rows : null}; res.render('pages/db', results ); client.release(); } catch (err) { console.error(err); res.send("Error " + err); } })

This action ensures that when you access your app using the /db route, it returns all rows in the test_table table.

Deploy your code to Heroku. If you access /db, you receive an error because there’s no table in the database. Assuming that you have Postgres installed locally, use the heroku pg:psql command to connect to the remote database, create a table, and insert a row.

$ heroku pg:psql--> Connecting to postgresql-asymmetrical-00466psql (14.7 (Homebrew))SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)Type "help" for help.shrouded-anchorage-35377::DATABASE=> create table test_table (id integer, name text);CREATE TABLEshrouded-anchorage-35377::DATABASE=> insert into test_table values (1, 'hello database');INSERT 0 1shrouded-anchorage-35377::DATABASE=> \q

Now when you access your app’s /db route with heroku open db, you see something like:

Getting Started on Heroku with Node.js | Heroku Dev Center (4)

Read more about Heroku PostgreSQL.

You can use a similar technique to install MongoDB or Redis add-ons.

Next Steps

Now you know how to deploy an app, change its configuration, view logs, scale, and attach add-ons. For more information, here’s some recommended reading.

  • For a technical overview of the concepts that you encounter while writing, configuring, deploying, and running applications, read How Heroku Works.
  • To learn more about developing and deploying Node.js applications, visit the Node.js category.
  • To understand how to take an existing Node.js app and deploy it to Heroku, read Deploying Node.js Apps on Heroku.
Getting Started on Heroku with Node.js | Heroku Dev Center (2024)
Top Articles
Latest Posts
Article information

Author: Ouida Strosin DO

Last Updated:

Views: 6366

Rating: 4.6 / 5 (56 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Ouida Strosin DO

Birthday: 1995-04-27

Address: Suite 927 930 Kilback Radial, Candidaville, TN 87795

Phone: +8561498978366

Job: Legacy Manufacturing Specialist

Hobby: Singing, Mountain biking, Water sports, Water sports, Taxidermy, Polo, Pet

Introduction: My name is Ouida Strosin DO, I am a precious, combative, spotless, modern, spotless, beautiful, precious person who loves writing and wants to share my knowledge and understanding with you.