NestJS ⚡ Multiple DB Setup with TypeORM
Tags: nestjs, javascript, database, typeorm
Published: 2022-05-07 03:37:50

## Introduction

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

[NestJS Documentation](https://docs.nestjs.com/techniques/database#multiple-databases) 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.

```typescript
...
@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      entities: [Customer],
      synchronize: true,
    }),
  ],
})
...
```
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](https://docs.nestjs.com/techniques/configuration). It is a simple process.

```typescript
...
@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,
        };
      },
    }),
...
```
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.

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

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.
{% gist https://gist.github.com/sanzoc/233f55258fda89664dc1039fa91e7122 %}


#### 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](https://docs.nestjs.com/techniques/database) and [TypeOrm Docs](https://typeorm.io/entities).
 

#### Use Main DB Connection
In order to have access to the Customer entity TypeOrm functionality we need to import TypeOrm into the Customer module. 
{% gist https://gist.github.com/sanzoc/e9bdd8288fafb998afc48423600de371 %}

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

{% gist https://gist.github.com/sanzoc/6aecb9c7cf92e6bffcdca1caaee57977 %}

#### 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.

{% gist https://gist.github.com/sanzoc/bccd3491899914eb419f444acd718f8d %}

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

{% gist https://gist.github.com/sanzoc/abcbf4e12453931bc1e07be06a4b4509 %}
 
## 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.