DEV Community

Carlos Santos
Carlos Santos

Posted on

NestJS ⚡ Multiple DB Setup with TypeORM

Introduction

Hi, in this post I will describe how to setup and use multiple database connections with a simple example.

NestJS Documentation is great for the most part but it has some important omissions on the multiple databases section.

I will proceed under the assumption that you already have created a NestJS application and have your 2 or more databases setup and ready to be connected to. Let's go straight to the point.

Let's get to it

Define DB connection options

Following NestJS docs we will find the connection options example credentials directly set on code.

...
@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      entities: [Customer],
      synchronize: true,
    }),
  ],
})
...
Enter fullscreen mode Exit fullscreen mode

Instead of having credentials exposed on the code like that we should use an environment configuration file or a similar strategy.

For this example we will make use of the @nestjs/config package to get the database credentials from an environment file. You can find more information about how to install and use the config package at NestJS Configuration Docs. It is a simple process.

...
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => {
        return {
          type: 'mssql',
          host: configService.get('MAIN_DB_HOST'),
          port: parseInt(configService.get('MAIN_DB_PORT')),
          database: configService.get('MAIN_DB_DATABASE'),
          username: configService.get('MAIN_DB_USERNAME'),
          password: configService.get('MAIN_DB_PASSWORD'),
          schema: configService.get('MAIN_DB_SCHEMA'),
          entities: [Customer],
          synchronize: false,
        };
      },
    }),
...
Enter fullscreen mode Exit fullscreen mode

We don't need to define a connection name four our first connection. It will be named 'default' by default 😬. For any other defined connections we will need to provide a name.

NestJS docs tells us that the name property should be added inside the options object, at the same level as host, port, etc.

...
@Module({
  imports: [
    TypeOrmModule.forRoot({
      ...defaultOptions,
      host: 'user_db_host',
      entities: [User],
    }),
    TypeOrmModule.forRoot({
      ...defaultOptions,
      name: 'albumsConnection',
      host: 'album_db_host',
      entities: [Album],
    }),
  ],
})
...
Enter fullscreen mode Exit fullscreen mode

Now, because we are getting our credentials from the .env file and using forRootAsync we need to add the connection name property outside of the useFactory function 👀. This is a really important detail that is not mentioned anywhere in the docs.

The final app.module.ts file should look like this.

Entities

We have created two entities for the sake of this excercise. Customer entity will use the main db connection and AccessLog entity will use the secondary db connection. For more information about TypeOrm Entity and Repository pattern check out NestJS TypeOrm Docs and TypeOrm Docs.

Use Main DB Connection

In order to have access to the Customer entity TypeOrm functionality we need to import TypeOrm into the Customer module.

And this is how we use it in the Customer service.

Use Secondary DB Connection

As we did for the main connection and the Customer entity we need to import TypeOrm into the AccessLog module, but this time we will also need to pass a connection name to the TypeOrmModule.forFeature([Entities, ...], connectionName) method.

And this is how we use it in the AccessLog service.


Conclusion

✅ We managed to setup a multiple db configuration with credentials values coming from an environment file.
✅ Defined what connection should each entity use.
✅ With the knowledge of how to add a secondary connection we should be able to add many more as needed.
✅ Learned about the little gotchas when initializing TypeOrm asynchronously.

I really hope this article was helpful.

If you have any feedback or found mistakes, please don’t hesitate to reach out to me.

Top comments (1)

Collapse
 
andrewbaisden profile image
Andrew Baisden

Great article definitely going to be using Nest.js a lot more for backend because it uses native TypeScript.