Tutorials on Heroku

Learn about Heroku from fellow newline community members!

  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL
  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL

Deploying a Node.js and PostgreSQL Application to Heroku

Serving a web application to a global audience requires deploying, hosting and scaling it on reliable cloud infrastructure. Heroku is a cloud platform as a service (PaaS) that supports many server-side languages (e.g., Node.js, Go, Ruby and Python), monitors application status in a beautiful, customizable dashboard and maintaining an add-ons ecosystem for integrating tools/services such as databases, schedulers, search engines, document/image/video processors, etc. Although it is built on AWS, Heroku is simpler to use compared to AWS. Heroku automatically provisions resources and configures low-level infrastructure so developers can focus exclusively on their application without the additional headache of manually setting up each piece of hardware and installing an operating system, runtime environment, etc. When deploying to Heroku, Heroku's build system packages the application's source code and dependencies together with a language runtime using a buildpack and slug compiler to generate a slug , which is a highly optimized and compressed version of your application. Heroku loads the slug onto a lightweight container called a dyno . Depending on your application's resource demands, it can be scaled horizontally across multiple concurrent dynos. These dynos run on a shared host, but the dynos responsible for running your application are isolated from dynos running other applications. Initially, your application will run on a single web dyno, which serves your application to the world. If a single web dyno cannot sufficiently handle incoming traffic, then you can always add more web dynos. For requests exceeding 500ms to complete, such as uploading media content, consider delegating this expensive work as a background job to a worker dyno. Worker dynos process these jobs from a job queue and run asynchronously to web dynos to free up the resources of those web dynos. Below, I'm going to show you how to deploy a Node.js and PostgreSQL application to Heroku. First, let's download the Node.js application by cloning the project from its GitHub repository: Let's walkthrough the architecture of our simple Node.js application. It is a multi-container Docker application that consists of three services: an Express.js server, a PostgreSQL database and pgAdmin. As a multi-container Docker application orchestrated by Docker Compose , the PostgreSQL database and pgAdmin containers are spun up from the postgres and dpage/pgadmin4 images respectively. These images do not need any additional modifications. ( docker-compose.yml ) The Express.js server, which resides in the api subdirectory, connects to the PostgreSQL database via the pg PostgreSQL client. The module api/lib/db.js defines a Database class that establishes a reusable pool of clients upon instantiation for efficient memory consumption. The connection string URI follows the format postgres://[username]:[password]@[host]:[port]/[db_name] , and it is accessed from the environment variable DATABASE_URL . Anytime a controller function (the callback argument of the methods app.get , app.post , etc.) calls the query method, the server connects to the PostgreSQL database via an available client from the pool. Then, the server queries the database, directly passing the arguments of the query method to the client.query method. Once the database sends the requested data back to the server, the client is released back to the pool, available for the next request to use. Additionally, there's a getAllTables method for retrieving low-level information about the tables available in our PostgreSQL database. In this case, our database only contains a single table: cp_squirrels . ( api/lib/db.js ) The table cp_squirrels is seeded with records from the 2018 Central Park Squirrel Census dataset downloaded from the NYC Open Data portal. The dataset, downloaded as a CSV file, contains the fields obs_date (observation date) and lat_lng (coordinates of observation) with values that are not compatible with the PostgreSQL data types DATE and POINT respectively. Instead of directly copying the contents of the CSV file to the cp_squirrels table, copy from the output of a GNU awk ("gawk") script. This script... ( db/create.sql ) Upon the initialization of the PostgreSQL database container, this SQL file is ran by adding it to the docker-entrypoint-initdb.d directory. ( db/Dockerfile ) This server exposes a RESTful API with two endpoints: GET /tables and POST /api/records . The GET /tables endpoint simply calls the db.getAllTables method, and the POST /api/records endpoint retrieves data from the PostgreSQL database based on a query object sent within the incoming request. To bypass CORS restrictions for clients hosted on a different domain (or running on a different port on the same machine) sending requests to this server, all responses must have the Access-Control-Allow-Origin header set to the allowable domain ( process.env.CLIENT_APP_URL ) and the Access-Control-Allow-Headers header set to Origin, X-Requested-With, Content-Type, Accept . ( api/index.js ) Notice that the Express.js server requires three environment variables: CLIENT_APP_URL , PORT and DATABASE_URL . These environment variables must be added to Heroku, which we will do later on in this post. The Dockerfile for the Express.js server instructs how to build the server's Docker image based on its needs. It automates the process of setting up and running the server. Since the server must run within a Node.js environment and relies on several third-party dependencies, the image must be built upon the node base image and install the project's dependencies before running the server via the npm start command. ( api/Dockerfile ) However, because the filesystem of a Heroku dyno is ephemeral , volume mounting is not supported. Therefore, we must create a new file named Dockerfile-heroku that is dedicated only to the deployment of the application to Heroku and not reliant on a volume. ( api/Dockerfile-heroku ) Unfortunately, you cannot deploy a multi-container Docker application via Docker Compose to Heroku. Therefore, we must deploy the Express.js server to a web dyno with Docker and separately provision a PostgreSQL database via Heroku Postgres add-on . To deploy an application with Docker, you must either: For this tutorial, we will deploy the Express.js server to Heroku by building a Docker image with heroku.yml and deploying this image to Heroku. Let's create a heroku.yml manifest file inside of the api subdirectory. Since the Express.js server will be deployed to a web dyno, we must specify the Docker image to build for the application's web process, which the web dyno belongs to: ( api/heroku.yml ) Because our api/Dockerfile already has a CMD instruction, which specifies the command to run within the container, we don't need to add a run section. Let's add a setup section, which defines the environment's add-ons and configuration variables during the provisioning stage. Within this section, add the Heroku PostgreSQL add-on. Choose the free " Hobby Dev " plan and give it a unique name DATABASE . This unique name is optional, and it is used to distinguish it from other Heroku PostgreSQL add-ons. Fortunately, once the PostgreSQL database is provisioned, the DATABASE_URL environment variable, which contains the database connection information for this newly provisioned database, will be made available to our application. Check if your machine already has the Heroku CLI installed. If not yet installed, then install the Heroku CLI. For MacOSX, it can be installed via Homebrew: For other operating systems, follow the instructions here . After installation, For the setup section of the heroku.yml manifest file to be recognized and used for creating a Heroku application, switch to the beta update channel and install the heroku-manifest plugin: Without this step, the PostgreSQL database add-on will not be provisioned from the heroku.yml manifest file. You would have to manually provision the database via the Heroku dashboard or heroku addons:create command. Once installed, close out the terminal window and open a new one for the changes to take effect. Note : To switch back to the stable update stream and uninstall this plugin: Now, authenticate yourself by running the follow command: Note : If you want to remain within the terminal, as in entering your credentials directly within the terminal, then add the -i option after the command. This command prompts you to press any key to open a login page within a web browser. Enter your credentials within the login form. Once authenticated, Heroku CLI will automatically log you in. Within the api subdirectory, create a Heroku application with the --manifest flag: This command automatically sets the stack of the application to container and sets the remote repository of the api subdirectory to heroku . When you visit the Heroku dashboard in a web browser, this newly created application is listed under your "Personal" applications: Set the configuration variable CLIENT_APP_URL to a domain that should be allowed to send requests to the Express.js server. Note : The PORT environment variable is automatically exposed by the web dyno for the application to bind to. As previously mentioned, once the PostgreSQL database is provisioned, the DATABASE_URL environment variable will automatically be exposed. Under the application's "Settings" tab in the Heroku Dashboard, you can find all configuration variables set for your application under the "Config Vars" section. Create a .gitignore file within the api subdirectory. ( api/.gitignore ) Commit all the files within the api subdirectory: Push the application to the remote Heroku repository. The application will be built and deployed to the web dyno. Ensure that the application has successfully deployed by checking the logs of this web dyno: If you visit https://<application-name>.herokuapp.com/tables in your browser, then a successful response is returned and printed to the browser. In case the PostgreSQL database is not provisioned, manually provision it using the following command: Then, restart the dynos for the DATABASE_URL environment variable to be available to the Express.js server at runtime. Deploy your own containerized applications to Heroku!

Thumbnail Image of Tutorial Deploying a Node.js and PostgreSQL Application to Heroku

Deploying Next.js Application on Vercel, Heroku, and a Custom Static Server

In this post, we will be looking at Next.js app deployment on different types of servers and using different technologies, such as: We will go through deployment setup on each technology step by step and show the code. Some time ago web-developers shipped their applications in production by hand. They might use FTP or some other protocols to copy built application assets to production server. This approach has a lot of downsides. Automatic deployment solves these problems by extracting the shipping process from development. Thus, it makes it possible to ship applications consistently, continually and automatically. Deployment in general is all the processes required to make an application available for use. In a case with a web-app typical deployment usually consists of building an app and uploading its assets to a server (production or staging). Deployment is automatic if all those actions happen without human interaction. So if a developer has to build an application themselves it’s not automatic deployment. Automatic deployment has many advantages: In our case, the deployment will consist of building an app and delivering its assets to a server. At the end of this post you will learn how to set up automatic deployments with Vercel, Heroku, and on your own server via SSH from your GitHub repo. We suppose you have a GitHub account—it will be needed throughout the whole post. We will use pull-requests as triggers to deployments. Also, we suppose you know what Next.js is and how to create applications using it. If you don’t know it yet, you can learn it from the 5th chapter of “Fullstack React with TypeScript” book and for this tutorial you can use our app starter pack . For the last section of this tutorial, we suppose you have a server with SSH access to it. You’re going to need one to be able to allow GitHub and GitHub Actions to upload app assets. Vercel is a solution for deploying applications built with Next.js from creators of Next.js. As it put in official Next.js documentation , it is “the easiest way to deploy Next.js to production”. Let’s try it. To connect Vercel and start deploying you’re going to need a GitHub repository. It will allow connecting Vercel to codebase and trigger deployment on new commits in the master branch. If you already have a repository with an application built with Next.js you can skip this section. Create a new repo at the  “New” page . If you don’t want to create a repository, you can fork ours with app starter files. Clone the project repository on your local machine and open the project. If the repository is empty, add application code, commit and push it. Vercel account allows you to connect your projects’ repositories and monitor deployments as well as see the deployment history. Create an account on the signup page . If you already have an account, you can skip this section. When you created an account you should have access to Vercel’s Dashboard . The dashboard is like a control panel. Here you will be able to see the last deployments of every application and recent activity of an imported project. Let’s import the project repo. Find the “Import project” button and hit it. You will be redirected to the “Import” page . On that page find the “Import Git Repository” section. Click ”Continue“ button in that section. You will see a form with an input that requires an URL of a git repository. Enter your project’s repository URL there and submit the form. When it’s done Vercel will redirect you to GitHub. There you will be asked by GitHub for permissions to repository. Allow Vercel read and write access to the selected repository. It is possible to allow third-party applications to read and write every repository you have, but not recommended by security reasons. Try to limit third-party application’s access as minimal as possible. After you grant permissions to Vercel, GitHub will redirect you back to the “Import” page. There you will see import settings: Keep the project name the same as the repository name to make it less ambiguous. The last two options may be useful if you have, for example, a custom build script. Let’s say, to build a project you use instead of standard npm run build some another command. In that case, you can override default command with your own in the “Build and Output Settings” section. Same with the “Environment variables”. Sometimes you might need to configure the build process from outside. Usually, it is done with environment variables that are passed via command line. The most often example is NODE_ENV variable, which configures what kind of build should be triggered. Its value set to production usually tells that this is a production build and should be optimized. In a case with Next.js application, we don’t need to configure anything except for a project name. When you set it up, hit the “Deploy” button. You will see the congratulations screen with a “Visit” link, which will lead to a freshly deployed app on vercel.app domain. Hit this link to open and inspect the current deployment. And that’s it! You just deployed an application and made it available for users! Now, return to the Dashboard for a minute. The new project will appear in a list of your imported applications. Click a link to your project. On a project page, you will see the ”Production Deployment“ section. It contains information about current production deployment, such as: Below, you should see a “Preview Deployments” section. This section contains non-production deployments, such as staging and testing deployments. Let’s say you want to test some features in the environment very close to production, but don’t want to ship an untested feature in production. Preview deployments will help you do that. By default to create a preview deployment, you need to create a pull-request (or merge-request) to default branch in your repository. Vercel will analyze the state of a repo and if there are some pull-requests to the default branch, it will deploy every new commit in this pull-request as preview deployment. To test it, create a new branch in the repository. Checkout to this branch on your local repo, make some changes in your code, commit and push them to the created branch. After that create a pull-request from a new branch to default. When it’s done, Vercel-bot will automatically deploy this pull-request as a preview and leave a comment right in pull-request. You won’t even need to return to the Dashboard to inspect your project, the link to preview will be in the bot’s comment! And of course, the preview deployment will appear in the list of preview deployments in Dashboard. Heroku is a container-based cloud platform for deploying and managing applications. It also allows you to automate deploys and trigger them by pushing to repository's default branch. The first step is basically the same as in the previous section. You’re going to need a GitHub repository. New commits in the master branch will trigger deployments on Heroku as well. If you already have a repository with an application built with Next.js you can skip this section. Create a new repo at the “New” page . If you don’t want to create a repository, you can fork ours with app starter files . Clone the project repository on your local machine and open the project. If the repository is empty, add application code, commit and push it. Heroku also allows you to monitor your connected apps and their activity. To connect Heroku with your GitHub repository you’re going to need a Heroku account. Go to the signup page and create an account. If you already have one, you can skip this section. When you have an account on Heroku, you should have access to its Dashboard . The Dashboard contains lists of all the connected apps and services. To create a new app find a “New” button and hit it. In a select chose “Create new app” option. It will redirect you to a page with the new app settings screen. There you will be able to choose a name for your app, and a region. The region can affect performance and download time. For example, for users in Europe app deployed to the US region might load a bit slower than for users in the US because of the distance a request should pass between a user and a server. When it’s done, add a new pipeline with the button below. A Heroku pipeline is a set of actions being performed over your application. Let’s say you want not to just deploy an app, but to test is first and only then deploy—this set of testing and deploying actions is a pipeline. Heroku Pipelines represent steps of the continuous delivery workflow. In this case you can select “Production” since we won’t run any tests and want to just deploy the application. After it’s done, you will be asked about the deployment method. There might be 3 options: The first one is convenient when you have a git repository and you want to deploy an app right from the command line . If you have a Heroku CLI installed, there is a special command for deploying from the command line: But since we’re using GitHub select the “Connect to GitHub” method. Then select a repository to connect to from a list below. You might be asked for repository permissions. Again, try to keep third-party app access as minimal as possible. When you grant permissions to Heroku you can set up automatic deploys for some branch. By default automatic deploys may be turned off, so don’t forget to check the checkbox in this section. When you turn them on, select a branch from which to deploy. By default it is master , but you can select any other branch in your repository. Optionally check “wait for CI to pass before deploy” to ensure your tests pass before a project goes to production if there are any. GitHub Actions are an automatization workflow for building, testing, deployment, and other routines. They allow you to create a custom life cycle for your app. So, you can setup code-linting, code-formatting, some code checks, and all. They are like robots that receive messages and do some stuff. Actions are being set up by YAML-files, that describe what to do and what triggers this action. To tell GitHub that there is an action that should be played, create a directory called .github , mind the dot in front of the title. This is the directory that contains all the actions and workflows for this repository. Inside of that directory create another one called workflows . A workflow is a set of actions. So if you want to chain some actions together in a list you can use a workflow. In workflows directory create a file called main.yml , this is the workflow. Open this file and paste this code inside: Let’s break it down. The first line describes the name of this workflow. When GitHub will run this workflow, in a workflow dashboard you will see a list of all created workflows. The next directive is on . It describes what events should trigger this workflow. In this case, workflow should be triggered on push event in the master branch of this repo. So when someone pushes to master branch this workflow will be played. For deployment with Heroku, there is an action called “Deploy to Heroku”. Open its page and scroll to the “Getting Started” section . There you will see an example of the workflow setup. Let’s examine it. jobs contains all the work to do. In this case, there is only one job to do— build . This job runs on ubuntu-latest , this is the type of a machine that runs a workflow. The steps directive describes what steps to perform. In the example, each step is a GitHub Action. Latter is being run with some arguments that are described with with directive. heroku_api_key should be generated and stored in the “Secrets” section in GitHub. For this, you’re going to need Heroku CLI. If you already have it installed you can skip this section. Heroku CLI makes it easy to create and manage your Heroku apps directly from the terminal. It allows you for example deploy right from your terminal. However in this case you need it for another reason. You need to generate heroku_api_key for the repository secrets section. This is done with Heroku CLI. To install Heroku CLI go to its page and select an OS that you use. Note that different OSs use different installation methods. When it’s done check if there are no errors by running: Then, authenticate with this command: You’ll be prompted to enter any key to go to your web browser to complete the login. The CLI will then log you in automatically. Thus, you will be authenticated in your terminal when you will use heroku CLI command. Notice YOUR_EMAIL in its response, this should be the same you set in heroku email of main.yml . To generate a new token open your terminal, check if Heroku CLI is installed and run As a response, you will get a generated token. Copy its value and create a new GitHub Secret with it. Go to the “Secrets” section in GitHub: Settings → Secrets → New Secret. Set HEROKU_API_KEY as a name and generated token as a value. Save this secret. GitHub will use this value and replace ${{secrets.HEROKU_API KEY}} with it at build time automatically. In your package.json update start script to be as an example below. Pay attention to $PORT environment variable, that must be specified . When it’s done you should be able to trigger deploys by pushing changes to the master branch. Try to update code and push to master . In Dashboard, you will see a new app in the list of apps. Click on it and you will be redirected to an “Overview” page. There you should see latest activity and all the settings for this project. Find the “Open App” button to visit your application and inspect it. Sometimes third-party solutions wouldn’t work. It might happen for many reasons: it can cost a lot, or due to security reasons, but it might happen. In this case, there is an option to deploy an application on your own server. In this section, we suppose you have a server with SSH access to it. It will be required later. The first step is basically the same as in the previous section. You’re going to need a GitHub repository. New commits in the master branch will trigger deploy. If you already have a repository with an application built with Next.js you can skip this section. Create a new repo at the  “New” page . If you don’t want to create a repository, you can fork ours with app starter files . Clone the project repository on your local machine and open project. If the repository is empty, add application code, commit and push it. You’re going to deploy an app via SSH. For this, there is an action called “ssh deploy” . It uses Node.js and integrates by YAML-file as other GitHub Action do. This GitHub Action deploys a specific directory from GITHUB_WORKSPACE to a folder on a server via rsync over ssh. This workspace is a directory that is created by checkout action we used before. The workflow will be: Let’s create a new file in .github/workflows directory called custom.yml . This is the file that will describe your new workflow. In this file write the name of the workflow and events that should trigger it. This code means that this workflow will be triggered on every new push in the master branch. The detailed explanation of every line of this code you can find in the section above. Then, describe jobs to do and steps. Here we tell GitHub to check out this code, it will create a workspace that can be accessed with GITHUB_WORKSPACE . The second action sets up Node.js with version 12. (LTS on the moment this post is being written.) Then describe build step: It will install all the dependencies, build the project, and export static files. next export allows you to export your app to static HTML , which can be run standalone without the need of a Node.js server. It works by prerendering all pages to HTML. The reason we use npx is because we didn’t install next CLI tools globally, so it won’t be found in GitHub Action runtime, which will cause an error. npx on the other hand will execute a local package's binary. The last step in the workflow is: It tells GitHub Actions to use ssh-deploy action and pass some of the environment variables: secrets. mean that the value will be requested in GitHub Secrets, and for this to work you're going to need to specify those secrets that should be stored in the “Secrets” section in your GitHub repository. Create 4 new secrets in your project. Go to the “Secrets” section in GitHub repository and create: Connect to your server via SSH. (You may be asked a password if you connect the first time.) When connected, generate a new key pair. Keep the passphrase empty. Specify the type of the key as RSA. You might want to set some unique name for the key, just to make it easier to find it later, so when a command-line ask you how to name the file, you can change it. When generated, authorize those keys, otherwise, the server might not allow “ssh-deploy” to connect. Note the ~/.ssh/key-name —that’s the full path to the key file. It may vary depending on your file structure on a server. Now copy the private key value and paste it as a value for SERVER_SSH_KEY in the “Secrets” section. When everything’s set, you can trigger new deploy. Push some changes to the master branch, and GitHub will run the workflow, which will build the app, export it and let ssh-deploy deploy it. In this post, we explained how to deploy your Next.js application using Vercel, Heroku, and how to deploy it on a custom server using SSH.

Thumbnail Image of Tutorial Deploying Next.js Application on Vercel, Heroku, and a Custom Static Server

I got a job offer, thanks in a big part to your teaching. They sent a test as part of the interview process, and this was a huge help to implement my own Node server.

This has been a really good investment!

Advance your career with newline Pro.

Only $30 per month for unlimited access to over 60+ books, guides and courses!

Learn More