Deploy NestJS typescript app to Heroku (Solved: 503 Error)
Tags: node, nestjs, heroku, typescript
Published: 2021-02-27 18:34:29

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ola8j0bihtjlfgzug5oj.png)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s4k25j1jauzw0aka12l3.png)

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](https://signup.heroku.com/) or login if you already have an account set up.

  2. Create a new app. 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eo7s7iuqfkfbnwkwi8wt.png)

  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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9bgc1yh672zqmpk58a4x.png)

  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](https://devcenter.heroku.com/articles/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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ui0zzhxywnwd3tmsko51.png)
 
    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`

  7. 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/orph66rgb9p9a7yqi8cm.png)