Deploying Node.js apps to Heroku
Tags: node, heroku, githubactions, hosting
Published: 2023-01-18 17:12:00

---
title: Deploying Node.js apps to Heroku
published: true
tags: ['node', 'heroku', 'githubactions', 'hosting']
canonical_url: https://sevic.dev/nodejs-deployment-heroku/
---

This post covers the main notes from setting up the Heroku CLI tool to CI/CD pipeline with [Github actions](https://sevic.dev/notes/github-actions-101/).

### Prerequisites

- Run the following command to install the CLI tool

```bash
curl https://cli-assets.heroku.com/install.sh | sh
```

- Create an account or log in if you already have an account

```bash
heroku login
```

### Node server

- Run the following commands for packages setup

```bash
npm init -y
npm i express
```

- Write basic server

```js
// server.js
const express = require('express');
const app = express();
const PORT = process.env.PORT || 8080;

app.get('/', (_, res) => res.send('Hello world'));

app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
```

- Configure `start` script

```json
// package.json
{
  "scripts": {
    "start": "node server.js"
  }
}
```

### Project setup

The following command will create a project with the provided name. Project URL will be `<PROJECT_NAME>.herokuapp.com`

```bash
heroku create -a <PROJECT_NAME>
git init
heroku git:remote -a <PROJECT_NAME>
```

Create a Procfile with a command for starting the server.

```bash
# Procfile
web: npm start
```

### Environment variables

The following commands can be used to set the provided environment variable and restart the server, show the list of already set variables, remove the provided variable and restart the server, and append the set variables to a local file (`.env` in this case). Heroku will set up the server port's environment variable (`PORT`).

```bash
heroku config:set VARIABLE_NAME=value
heroku config
heroku config:remove VARIABLE_NAME
heroku config -s >> .env
```

### Addons

The following commands add and remove specified add-ons.

```bash
heroku addons:create <ADDON_NAME>
heroku addons:remove <ADDON_NAME>
```

### Databases

#### Redis

Run the following commands to provision the Redis database. Heroku will set the environment variables for the database connection.

```bash
heroku addons:create upstash-redis:free
```

#### Postgres

Run the following command to bootstrap a Postgres database.

```bash
heroku addons:create heroku-postgresql
```

The previous command will set the database connection string in `DATABASE_URL` environment variable.

Check the database info with the following command.

```bash
heroku pg:info
```

Release command in Procfile can run migrations.

```bash
# Procfile
release: npm run migrate
```

The following commands create the database backups, check the progress of the last backup, and show the list of the previous backups.

```bash
heroku pg:backups:capture
heroku pg:backups:info
heroku pg:backups
```

### Debugging

- Get the real-time logs

```bash
heroku logs --tail
```

- Get the specific number of lines of logs

```bash
heroku logs -n 20
```

- Get the info about the app

```bash
heroku info
```

- Get the state of the project to check if there are any issues

```bash
heroku status
```

- Run bash on the app dyno

```bash
heroku run bash
```

- Restart the app dynos

```bash
heroku restart
```

### Deployment

#### Manual deployment

Deploy and open the deployed version with the following commands.

```bash
git add .
git commit -m "Initial commit"
git push origin master
heroku open
```

If the command for opening the project in the browser doesn't work in Windows Subsystem for Linux, set `BROWSER` environment in the corresponding shell configuration file (e.g., `~/.zshrc`)

```bash
export BROWSER=wslview
```

#### CI/CD pipeline

Connect the app with Github on Deploy &#8594; Deployment method page and enable CI and automatic deploys.

Add `.github/workflows/config.yml` file with the following configuration for the CI pipeline.

```yml
name: CI pipeline

on:
  push:
    branches:
      - master

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    container: node:20.9.0-alpine3.17

    steps:
      - name: Github checkout
        uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - run: npm ci

      - run: npm run lint

      - run: npm test

      - run: npm audit
```

### Boilerplate

Here is the [link](https://sevic.dev/nestjs-starter) to the boilerplate I use for the development.