Why is my Node.js app crashing with an R10 error?

Resolution

Using process.env.PORT

Most Node.js apps bind to a specific port by default. For example, Express uses the following:

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

However, Heroku dynos expose a dynamic port for your app to bind to. This value is exposed in the $PORT env var. You must change your code to bind to this port instead. For example:

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Our app is running on port ${ PORT }`);
});

This will use the $PORT env var if available, or fallback to a default port (useful for local development). Note that when browsing to your application on Heroku, you still use port 80 ([your-application].herokuapp.com) and not the port that your process binds on.

Binding on 0.0.0.0

In rarer cases, your app may be using process.env.PORT, but may still be failing to bind. This can be caused by the app attempting to bind on localhost. Instead, you may need to change this to 0.0.0.0.

Running long build processes as part of npm run start

Finally, an R10 boot timeout can also be caused when the command to boot the server is also running another command, for example a build process such as grunt, gulp or webpack e.g.

"start": "npm run build && node server.js"

These tasks should instead be moved to a postinstall task as described here: https://devcenter.heroku.com/articles/node-best-practices#hook-things-up

"postinstall": "npm run build",
"start": "node server.js"

This will make sure that any long running build processes happen during a deploy and run once, rather than blocking the server from starting every time the dyno restarts.

Using webpack-dev-server

Whilst we don't recommend using a development server, if you are using this you need to specify the port and bind address like so:

webpack-dev-server --port $PORT --host 0.0.0.0