Photo by Rob Curran on Unsplash

How we ended up choking our database right before a demo call, by following official guidelines!

Aashish Peepra
3 min readNov 3, 2023

--

Well the documentation is not to blame here. But it kind of is. At Commenda we use Prisma as our ORM and Nest.js as our backend framework. When I started writing the backend from scratch back in March 2023, I followed the guidelines listed here.

You need to understand the problem before you can see my innocence

For those who are unfamiliar with Nest.js, it is a javascript framework built on top of express and fastify. Why I preferred Nest.js over simply writing in express? That’s a story for another blog. The only 2 things that you need to know about Nest.js are

Modules

Nest.js have a concept of module, where a module is an encapsulation of your controller, services/providers and other modules that you import. Imagine you have Users table, then for this you will have certain API endpoints in your controller.

 @Get("/me")
async getCurrentlyLoggedInUser(@User() guardUser: GuardedRequest){
return this.authenticationService.getOneUser(guardUser)
}

Then you will have a service layer where you will write the actual business logic for this, which the above controller will consume.

Module is that single file where you import and place all these controllers and providers together. Also modules are singelton classes.

@Module({
imports: [CompanyModule],
controllers: [UserController],
providers: [UserServices],
exports: [UserServices],
})

Services

Second important thing about Nest.js is the services. This is the place where you define your business logic. One important thing to remember is, every module that wants to consume this service needs to import the service’s related module. I know it’s a bit hard to digest. I will explain this more in details later. But simple rule of thumb is : If you want to use a serviceA in your moduleX, then import the moduleA in your moduleX, don’t import serviceA directly, otherwise the service class A, will initialise every time you import it. There are thousand more reasons I can give why not to import services directly, but for now just trust me.

So what actually happened?

Look carefully at the resource blog provided by official Nest.js website on “how to integrate Prisma”. Were you able to find the flaw?

Let me help you. Look at this piece of code first:

import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
}

They created a PrismaService class. Which makes sense. Then they used the service in another service. Which makes sense

import { Injectable } from '@nestjs/common';
import { PrismaService } from './prisma.service';
import { Post, Prisma } from '@prisma/client';

@Injectable()
export class PostService {
constructor(private prisma: PrismaService) {}
}

Then the first intuition is to directly import PrismaService in your PostService. Right? Righttt? I did the exact same thing. But do you remember what I told you about Nest.js services 1 minute ago? Never directly import services.

What happened is, throughout the app, we imported PrismaService directly. Every time, a module will get initialised, so will the Prisma service. Every time the Prisma service is initialize, a new connection is opened to the database. Hence number of connections to the database became equivalent to number of modules we have in our system.

When did we figure out something was wrong?

Ofcourse right before a client demo. I received a message saying, “We are running short on database connections”. I was stunned as everything was working fine a few hours ago. But one of the team members had just created a new module, this was the 40–45th module and boom. We exceeded the official connection limit. Ultimately we figured out what the reason was.

I’m writing this blog so if there is another developer who subconciously decided to import PrismaServices directly into their modules, please don’t do that. Create a PrismaModule before it’s your demo day.

--

--

Aashish Peepra

Software Engineer @commenda-eng | 100K+ people used my websites | Mentored 28K+ Developers globally | Google Solution challenge global finalist