Alex Merced I am a developer, educator, and founder of

Heroku alternatives to deploy a Node.js app

6 min read 1922

Heroku 3 Free Alternatives

For years, Heroku’s free tier has been the standard by which many developers released prototypes, hobby projects, and portfolio pieces to the public.

Unfortunately, Heroku announced plans to retire its free tier beginning on November 28th, 2022, leaving many developers scrambling to find alternatives to host their Bootcamp and portfolio projects.

In this article, we’ll review several alternatives to using Heroku for deploying apps. We’ll build a simple, framework-free Node.js app, and then deploy it to three different services that offer a free tier, Render, Railway, and We’ll also explore some Heroku alternatives for static deployment and serverless functions. Let’s get started!

Jump ahead:

Building our test app

We’ll build a plain vanilla Node.js server, but the same principles would apply if you’re using any of the popular Node.js frameworks, like Express, Koa, Fastify, NestJS, FoalTS, etc. You should already have Node.js installed on your machine.

Open your editor to an empty folder. Create a new Node.js project from your terminal using the npm init -y command.

Create an index.js file called touch index.js. In package.json, let’s set up our start script with the command below:

  "scripts": {
    "start": "node index.js"

Inside index.js, run the following code to configure a basic “Hello, World!” Node.js server:

// Import http library
const http = require("http")
// use env variable to define tcp/ip port with a default
const PORT = process.env.PORT || 8080
//create our server object
const server = http.createServer()
// We define a function that runs in response a request event
server.on("request", (request, response) => {
  // handle request based on method then URL
  response.statusCode = 200
  response.write("Hello World")
// get the server to start listening
server.listen(PORT, err => {
  // error checking
  err ? console.error(err) : console.log(`listening on port ${PORT}`)

Let’s test this locally by running node start and then heading to localhost:8080. If you see “Hello, World!”, then it’s working, and you can begin deploying it. From your terminal, create a git repository called git init. Add all of your files to staging with the git add . command, then make a commit with git commit -m"First Commit".

Next, head over to, create a new repository, and get the URL. Add your repo as a remote to your local repo, and be sure to use your URL:

git remote add origin

Then, push your code up to remote git push origin main. You can confirm whether your branch is main or master with the command git branch.

Now that we have our example code on GitHub, we can begin deploying it. For reference, you can check out my repo for this tutorial.

Deploying to Render

Render’s free tier makes static deployments for React, Vue, and Angular apps easy, as well as web service deployments for Node.js apps. Just follow these steps:

  • Log in to using your GitHub account
  • Click New > Web Service
  • Connect the GitHub repository you just created
  • On the next screen, give your project a name, accept all defaults and the free tier, and then deploy

From the following screen, we wait for the deployment to complete, which can take a while. In the upper left hand corner, you can find the URL for when it is done:

Deploy App Render Complete

Once it’s done, click on the URL that was generated for you, and you should see our “Hello, World!” message. That was pretty easy, wasn’t it!

Render offers other services that you may find useful as you build your application, like databases and cron jobs, which are scripts that run on a set schedule.

Deploying to Railway

Similar to Render, Railway is a service that allows you to deploy your application and provision several types of databases, like Postgres, mySQL, and MongoDB. The steps to deploy our Node.js application on Railway will be very similar to those for Render:

  • Log in using your GitHub account
  • Create a new project and select deploy from GitHub
  • Select your repo, then select deploy now

It should complete pretty quickly, and you’ll see the following screen:

Deploy App Railway Github Complete

By default, it will not have a publicly accessible domain name. To generate one, head over to the Settings tab and click Generate Domain; this will create a URL that you can use to share your project with others. That’s it!

Deploying using focuses primarily on deploying Docker containers, and over the last few years, it has made the process much easier. First, sign up using your GitHub account. We’ll take a different approach when deploying with

  • Install’s command line tool, FlyCtl
  • Log in with the command flyctl auth login. It will ask for payment info, but you won’t be charged as long as you remain within the free tier
  • From the terminal, deploy the app with flyctl launch
  • Answer the prompts and accept the defaults, then wait for the deployment to finish

It may take a while, but once it is deployed, you’ll see the application on your dashboard as well as the URL where it is located.

If you need to update your app in the future, simply run the flyctl deploy command from the directory where your application is. When you ran flyctl launch, it created a fly.toml file with all the deployment settings for speeding up updates, so it knows which deployment to update.

If it doesn’t work, double check that the port that is exposed in fly.toml is the same one that is exposed in your index.js on line 4 as the default port.

Heroku alternatives for static deployment

Not every application requires you to deploy a server; for example, frontend React, Vue, SolidJS, Svelte, and Angular apps can be deployed as static apps.

There are several options for deploying these static apps for free that only require you to connect your GitHub repository with your project, including Render, Railway,, Netlify, GitHub Pages, Vercel, App by Digital Ocean,, Firebase, and Azure Static Apps.

Instead of persistently running server code on the providers’ severs, only the static HTML, CSS, and JavaScript files in your project are being delivered. Therefore, there are fewer free options.

Static deployment on Render

To deploy a static site on Render, go to your dashboard and add a new Static Site:

Render Static Deployment

From here, you just have to connect the repository with your static website, specify any build commands like npm run build for React, then click deploy.

Static site deployment on Netlify

Log in to, then click Add new site from the dashboard:

Netlify Static Site Deployment

Then, select a GitHub repository:

Select GitHub Repository Netlify

Set your build command and publish directory, which will differ based on what frontend framework you use:

Set Build Command Publish Directory

Finally, click Deploy site, and you’re done!

Static site deployment on Vercel

Log into Vercel; from the dashboard, click on Add New, then select Project:

Vercel Static Site Deployment

Select a GitHub repository to deploy:

Select Vercel GitHub Repository

Set up your build command and output director, then click deploy:

Vercel Build Command Output Director Deploy

Static site deployment on Digital Ocean’s App platform

Head over to the Apps section of the Digital Ocean dashboard, then click on Create and select Apps:

Digital Ocean Create Apps Section

Select a GitHub repository with your application and pass it the necessary configurations, like the source directory:

Select Digital Ocean Github Repo

On the next page, we‘ll set our app to deploy as a static site:

Digital Ocean Deploy Github Static Site

To deploy a backend service like Heroku, you can also select Web Service, but this is not free on Digital Ocean. After changing it to a static site, make sure to check the build command and output directory:

Digital Ocean Check Build Command Output Directory

Click on Review and then Create Resource, and your app will be deployed!

Static site deployment on GitHub Pages

On any GitHub repository that holds a static site, just go into the Settings section and click on Pages:

Github Pages Deploy Static Site

Next, select a branch to deploy and save, and in a few minutes, the site should be live:

Github Repo Select Branch

Serverless functions

Serverless functions are another option for handling backend database interactions and API delivery, which is what we would normally deploy server applications for.

Instead of writing your server that runs 24/7, you can write functions with your desired logic that run on demand on the provider’s servers. All of the major clouds, like AWS, Azure, and Google provide serverless functions as a service, but there are other services that make using serverless functions much easier.

Usually, these services require you to connect a GitHub repo with one file for each function you want to deploy, which is then assigned a URL that you can call from your frontend application.

Using serverless functions on Netlify

To add a bit of backend functionality into your static apps deployed on Netlify, simply create a /netlify/functions folder in your repository .You can add as many JavaScript files in this folder as you’d like; for example, let’s imagine I created a /netlify/functions/cheese.js file that looked like the following:

exports.handler = async function (event, context) {
  return {
    statusCode: 200,
    body: JSON.stringify({ cheese: "Gouda" }),

When the code above is deployed to Netlify, it’ll create a route that you can make requests to at /.netlify/functions/cheese. You can use any of the libraries loaded in the project’s package.json, so connecting to databases and other typical backend activities are all fair game.

Using serverless functions on Vercel

To use serverless functions with static apps deployed on Vercel, you can use Vercel functions, which have a similar feel to ExpressJS when you use JavaScript.

Simply create your JavaScript or TypeScript files in a folder called /api in your project. For example, let’s say I create a file called /api/cheese.js that does the following:

export default function handler(req,res) {
  res.json({cheese: "gouda"});

When I deploy my application to Vercel, I can make any API request to /api/cheese to get back the response from this function.

Heroku’s main purpose was to deploy dynamic server applications. Beyond the free options from Render, Railway, and, some other paid options work along the same lines, connecting your GitHub repo and releasing your app:

  • App Platform from Digital Ocean: Starting at $5/mo
  • AWS Amplify: Pricing depends on the cost of the AWS resources needed to run app


Yes, it’s a little disruptive that we’ve lost Heroku’s free tier, but the resulting splintering across many different services like Render, Railway, and will make the industry more resilient. With developers no longer beholden to one vendor, the competition for market share will accelerate the drive to innovation:

Provider Free static deployment Free server deployment Free serverless functions Paid entry point No Yes No Metered prices
Render Yes Yes No Starter projects $7/mo
Railway Yes Yes No Metered pricing
Heroku No No No $5/mo
Netlify Yes No Yes $19/ mo
GitHub Pages Yes No No None
Vercel Yes No Yes $20/mo
App by Digital Ocean Yes No No $5/mo enabling server/static
Firebase Yes No Yes Metered pricing Yes No No $30/mo

I hope you enjoyed this article. Be sure to leave a comment if you have any questions, and let me know which service you prefer as an alternative to Heroku. Happy coding!

200’s only Monitor failed and slow network requests in production

Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third party services are successful, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens while a user interacts with your app. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. .
Alex Merced I am a developer, educator, and founder of

Leave a Reply