1.) 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.
2.) Binding on localhost
instead of 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
.
3.) 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
While 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