DEV Community

Cover image for Deploy NestJS typescript app to Heroku (Solved: 503 Error)
Rosy Shrestha
Rosy Shrestha

Posted on • Updated on

Deploy NestJS typescript app to Heroku (Solved: 503 Error)

Deploying applications on Heroku is pretty straightforward in most cases. But I ran into a problem while deploying my NestJS application that included TypeScript.

The build succeeded but I kept running into 503 service unavailable error.

image

image

It took me a while to figure out the problem. Turns out we need some of the devDependencies in package.json for the app to run properly since we are performing the TypeScript build on the server.

To future me, here are the steps to deploy NestJS app, which includes TypeScript, to Heroku:

  1. Sign up at Heroku or login if you already have an account set up.

  2. Create a new app.
    image

  3. Then you'll be redirected to a page where you have options to choose deployment methods. Clear instructions are provided in all of the available options.

    I picked Github for convenience.

    image

  4. In your NestJs project folder, add an optional dynamic port since our web server will be assigned a dynamic port by Heroku and we cannot statically define the port through which our application will listen.

    await app.listen(process.env.PORT || 3000);

  5. If you use nest-cli to create your NestJS application, the package.json includes the following command that runs our app in production mode. And if not, add it manually:

    "start:prod": "node dist/main.js"

    Now, create a file called Procfile, without any file extension at the root of your project. Heroku uses the procfile to know the commands to start our application. Add the following in the file:

    web: npm run start:prod

    or

    web: yarn start:prod

  6. Now for the important step that I messed up. Heroku sets the NODE_ENV to production and NPM_CONFIG_PRODUCTION flag to true by default and installs production dependencies only.

    To install devDependencies, set config vars NPM_CONFIG_PRODUCTION to false.

    You can add/edit config vars using Heroku dashboard. The option is available under the app's settings tab.

    image

    Or as an alternative, heroku-cli can be used.

    heroku config:set NPM_CONFIG_PRODUCTION=false

    Edit: Not all devDependencies (like prettier, eslint) are required so it's preferable to move necessary dependencies for production from devDependencies to dependencies

  7. Make sure to add the following in .gitignore file to exclude them from deploying to Heroku

    /dist
    /node_modules

  8. Commit and push your changes to the remote repository. And, deploy your changes via any of the available integrations.

    Either by using Heroku cli
    git push heroku <branch_name>

    Or using the Github deployment method from the Heroku dashboard

    image

Latest comments (17)

Collapse
 
kimkyeseung profile image
Kim Kyeseung

Interesting! but how distinguish dev and prod environment??

Collapse
 
emiperalta profile image
Emiliano Peralta

Thanks!

Collapse
 
lazaroofarrill profile image
Lazaro O'Farrill • Edited

Great article, just wanted to point out that step 6 is not correct. That is what you would do if you didn't go through step 5. If you setup the Procfile to run start:prod you don't need development dependencies.

Collapse
 
rosyshrestha profile image
Rosy Shrestha

Thanks for the feedback !

Collapse
 
sinxwal profile image
Sergio Tskhovrebov

Great job!

Collapse
 
saeed_sharman profile image
Md Saeed Sharman

I did not change the NPM_CONFIG_PRODUCTION flag but added required depenencies and was able to deploy successfully.

"dependencies": {
"@nestjs/cli": "^8.0.0",
"@nestjs/axios": "0.0.3",
"@nestjs/common": "^8.0.0",
"@nestjs/core": "^8.0.0",
"@nestjs/platform-express": "^8.0.0",
"@types/cache-manager": "^3.4.2",
"@types/express": "^4.17.13",
"@types/node": "^16.0.0",
"cache-manager": "^3.6.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0"
},

Collapse
 
bastiw profile image
Sebastian Weiß

Thanks a log :)

I am using it with fastify and I was required to add process.env.HOST to the listen too. Something like

const port = process.env.PORT ?? 3000;
const host = process.env.HOST || '0.0.0.0';

.....
await app.listen(port, host);

Enter fullscreen mode Exit fullscreen mode
Collapse
 
nachocapodanno profile image
Nacho Capodanno

Thanks dude! Great info!! Very Helpful @ @nilsjansen

Collapse
 
justin_m_morgan profile image
Justin Morgan

In point 6 (devDependencies), what devDependencies were required (or should be moved to "dependencies")?

Collapse
 
rosyshrestha profile image
Rosy Shrestha

As far as I remember, for me they were dependencies like some of the typescript packages.

Collapse
 
cloudkungfu profile image
Javel Rowe

This was super handy! Thanks much

Collapse
 
karkipy profile image
Aashish Karki

ayyyy thank you for this

Collapse
 
sabopriest profile image
PRIEST SABO

Thanks for this

Collapse
 
andres_arcila_c4de0c8a556 profile image
Andres Arcila

U help me Thanks !!

Collapse
 
laakhey profile image
Bikash Shrestha

Thanks! this helped a lot.

Collapse
 
nilsjansen profile image
Nils Jansen

Great post! I was looking for a solution to this for way too long. Most tutorials say "just include /dist in the git repository" which really messes things up when trying to merge branches etc. :D

Collapse
 
rosyshrestha profile image
Rosy Shrestha

Thank you @nilsjansen :D I had to go through many resources to come to a solution. I thought it was just me.
Glad this helped you :)