Building a NestJS App on Railway
Nestjs is a javascript framework with a typescript flavour. Often described as the swiss-army of javascript backend applications, it allows you to write following an object-oriented programming paradigm or functional programming and is easily a good switch for anyone coming from a non-js background to make the switch.
This article covers the nitty gritty of getting out Nestjs running on Railway. Here is the link to the project we will build in GitHub.
Let's get started.
You can use your preferred cli
tool on your machine to get started.
To create a new project, just type the commands below sequentially
- Install nestjs:
npm i -g @nestjs/cli
- Create a new nestjs project:
nest new rail-nest
The project name is rail-nest
which can be replaced with any name you like.
- Run the command below to enter the new project directory and start the nestjs project locally on your machine:
cd rail-nest
npm run start
If you navigate to http://localhost:3000
on your browser, you should get a positive response showing your nestjs application is running.
To have an application that can easily scale, where we can continually add more components as our application grows, containerization is a great approach to ensuring we can have an all-in-one application.
To get started, we need to create a Dockerfile, where we can add detailed instructions for our Docker applications.
- In your
cli
, run the command below to create aDockerfile
and a.dockerignore
in your project root directory.
touch Dockerfile .dockerignore
- Then let's add the instruction below to the Dockerfile
# Base image
FROM node:20
# Create app directory
WORKDIR /usr/src/app
# A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./
# Install app dependencies
RUN npm ci
# Bundle app source
COPY . .
# Creates a "dist" folder with the production build
RUN npm run build
# Expose the port on which the app will run
EXPOSE 3000
# Start the server using the production build
CMD ["npm", "run", "start:prod"]
- Add the following to your
.dockerignore
.
Dockerfile
.dockerignore
node_modules
npm-debug.log
Dist
Now let’s deploy the project to Railway. See Railway docs for reference if needed.
- Push the NestJS code to a github repo.
- On your project canvas in Railway
- Create a new project
- Add a new Github service
- Select your Github repo
- Connect your github repo to the source repo in the source section.
- Apply changes to deploy the app
The setup ensures that the database, migrations, queues and scheduled tasks are all operational and can run seamlessly.
We will start by using the Nestjs cache manager, the native cache manager stores the cache in memory, we will then configure the cache to be stored in Redis.
- Install this cache manager package via your cli:
npm install @nestjs/cache-manager [email protected] @nestjs/config
- Then import the
CacheModule
into yourapp.module.ts
:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { CacheModule } from '@nestjs/cache-manager';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ConfigModule.forRoot(),
CacheModule.register()
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Implement the cache module globally (Optional)
If you want to leverage the cache module across different modules, you can pass the isGlobal
flag property:
CacheModule.register({ isGlobal: true })
For example, here's a CacheModule implementation applied globally to a NestJS app in the app.module.ts
file:
import { CacheModule, Module } from '@nestjs/common';
import * as redisStore from 'cache-manager-redis-store';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
CacheModule.register({
isGlobal: true,
}),
],
})
export class AppModule {}
Implement Redis for caching
Up to this point, our cache will be stored in memory, to migrate easily to Redis, we will need to update the cache module configuration and also create a Redis server in Railway.
- Let's install the relevant packages:
npm install [email protected]
npm install --save-dev @types/cache-manager-redis-store
- Now, proceed to change the cache module to use Redis.
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CacheModule } from '@nestjs/cache-manager';
import * as redisStore from 'cache-manager-redis-store';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
CacheModule.register({
isGlobal: true,
store: redisStore,
host: process.env.REDISHOST,
port: process.env.REDISPORT
})],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
- After, we will tweak our cache module to the instruction below:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
import { CacheModule, CacheStore } from '@nestjs/cache-manager';
import { redisStore } from 'cache-manager-redis-store';
@Module({
imports: [
ConfigModule.forRoot(),
CacheModule.registerAsync({
isGlobal: true,
useFactory: async () => {
const store = await redisStore({
socket: {
host: process.env.REDISHOST,
port: +process.env.REDISPORT,
},
url: process.env.REDISURL,
password: process.env.REDISPASSWORD
});
return {
store: store as unknown as CacheStore,
ttl: 60 * 60 * 24 * 7,
}
}
})
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
All set locally, simply push to your github repo the latest changes.
Add Redis to the Railway project
Now let’s add a Redis service in Railway and connect it to NestJS.
- On your railway project canvas, create a new redis service.
- Head back to your App service and click on Variables.
- Add all necessary environment variables
REDISHOST="${{Redis.REDISHOST}}"
REDISPASSWORD="${{Redis.REDIS_PASSWORD}}"
REDISPORT="${{Redis.REDISPORT}}"
REDISURL="${{Redis.REDIS_URL}}"
- Click Deploy
View of NestJS project in Railway with Redis
Currently, we have Redis infused into our Nestjs app. Let's add the postgres database.
- Locally, we are going to add
typeorm
and thepostgres
adapter package.
npm install @nestjs/typeorm typeorm
npm install pg
- Then add the following in our
app.module.ts
TypeOrmModule.forRootAsync({
useFactory: () => ({
type: 'postgres',
host: process.env.POSTGRESHOST,
port: +process.env.POSTGRESPORT,
username: process.env.POSTGRESUSER,
password: process.env.POSTGRESPASSWORD,
database: process.env.POSTGRESDB,
synchronize: true,
entities: []
})
})
Note the values in the env
are random variables and should be replaced with their original representation based on your setup.
- Simply push to your github repo the latest changes.
Add Postgres to the Railway project
Now let’s add the Postgres service to our Railway project and connect it to NestJS.
- On your railway project canvas, create a new Postgres service.
- Head back to your App service and click on Variables.
- Add all necessary environment variables
POSTGRESDB="${{Postgres.PGDATABASE}}"
POSTGRESHOST="${{Postgres.PGHOST}}"
POSTGRESPASSWORD="${{Postgres.PGPASSWORD}}"
POSTGRESPORT="${{Postgres.PGPORT}}"
POSTGRESUSER="${{Postgres.PGUSER}}"
- Click Deploy
View of NestJS project in Railway with Postgres
Let us add a task scheduler in Nestjs.
- Installing the packages below:
npm install --save @nestjs/schedule
npm install --save-dev @types/cron
- Add the instruction below to your
app.module.ts
import section:
ScheduleModule.forRoot()
Nestjs schedule runs alongside your main application, by integrating the cron functionality directly into the application lifecycle.
- A final push to the github repo and our setup is complete.
Let’s make the NestJS app available on the public internet.
- Navigate to the Networking section under the Settings tab of your new service.
- Click Generate Domain to create a public URL for your app.
We now have a fully functional Nestjs application running in Railway!
Let’s explore one more option for starting a NestJS project in Railway.
Railway provides templates as a way to get started almost immediately with your NestJS project, enabling you to provision a service or set of services by simple clicks.
If you’re looking for the fastest way to get started, the one-click deploy option is ideal. It sets up your Nestjs app along with a Redis database, a Postgres database and the Nestjs scheduler. Just click the button below to get started.
After deploying, we recommend that you eject from the template to create a copy of the repository under your own GitHub account. This will give you full control over the source code and project.
With that, we've successfully set up a Nestjs application coupled with everything needed to get started immediately, database, caching and cron schedule inclusive. You should also be able to use this as a reference to deploy your Nestjs application from scratch or via Github. There is no limit to what you can do, and can decide to extend to other Railway compatible service.