Netlify functions not retaining Singleton Database connections?

Netlify functions not retaining Singleton Database connections?

I am using:

  • MongoDB Driver
  • Node.js v12 and Express.js
  • serverless-http
    I am trying to use MongoDB Driver and I have created a DatabaseService singleton class. But I have noticed that the database connection is not being re-used.
    Do Netlify Functions allow Singleton classes?
    How can I reuse the MongoDB Client connection in a separate module?
    Any help would be greatly appreciated!

Hi @gitaalekhyapaul, welcome to the Community!

One thing to note is that each lambda function runs in its own separate ‘container’. So, if one function opens a connection to your DB, another function won’t be able to re-use that connection since it isn’t on the same ‘container’. Let me know if that makes sense. Otherwise, can you provide more context/details on what you are trying to do and we can go from there?

Thank you for replying @Dennis
I tried using this as my DatabaseService singleton. It is not working when I am calling it in the controllers:
I was not able to share any object data from different modules also.
For example, the following Database Service code in the Node runtime, but when compiled using netlify-lambda, the following code fails to work.

import * as MongoDB from "mongodb";
​
/**
 * Drives a database connection in a singleton.
 */
export class DatabaseService {
  public database: MongoDB.Db | null = null;
​
  private client: MongoDB.MongoClient = new MongoDB.MongoClient(
    process.env.DB_URL || "",
    { useUnifiedTopology: true }
  );
  private static instance: DatabaseService;
​
  constructor() {
    this.initialize();
  }
​
  /**
   * Initializes the database
   */
  private async initialize(): Promise<any> {
    try {
      const client = await this.client.connect();
      this.database = client.db(process.env.DB_NAME);
      console.log(
        `Established connection to database <${this.database.databaseName}>`
      );
    } catch (error) {
      console.log(
        `Failed to established connection to database <${process.env.DB_NAME}>`
      );
    }
  }
​
  /**
   * The static method that controls the access to the DatabaseService instance.
   */
  public static getInstance(): DatabaseService {
    if (!DatabaseService.instance) {
      DatabaseService.instance = new DatabaseService();
    }
​
    return DatabaseService.instance;
  }
}

We won’t be able to help debug your code so let’s focus back on what Dennis asked:

Are you trying to reuse a connection ACROSS FUNCTION INVOCATIONS? this could be two invocations of the same function, or two different functions. They all run in completely separate containers, and cannot share or reuse connections or local data (except the local read-only data that you might deploy with your function).

@fool so the solution is to connect to a db before the logic of the function, then close db connection at the very end. Right?

Hiya, @sandorTuranszky :wave:

Thanks for your patience here-- I recognize this thread has been a bit quiet since you reached out. Let us know if you ended up trying the steps you shared above, or if you are still seeking assistance. :slight_smile:

@hillary would be great the best strategy to handle DB connections from Netlify functions.I would like to reuse connections as much as possible but I do not know what is the lifespan of each function.

If 5 requests within 10 seconds create 5 functions, I do not know if they use the same connection or create 5 DB connections.

In development during testing I can see that there are up to 20 connections to my serverless Redis instance while I am the only user. This is confusing.

Hi, @sandorTuranszky. The five function HTTP requests would likely create five separate function instances so they would not be able to share a connection.

Note, Netlify Functions are built using AWS Lambda. Any solutions or limitations for Lambda will likely also apply to Functions.

I don’t know if this is possible or not for databases hosted outside of AWS. You might search for existing examples of reusing database connections with Lambda functions to see if there is a way to do this.

According to this (Optimizing AWS Lambda With MongoDB Atlas & NodeJS | MongoDB Blog) article, it should be possible to reuse a db connection for quick, multiple sequential requests. Lambda also supports this. But when I tried it on netlify, it is creating a new db connection for each invocation. Is this because of the way netlify internally handles the functions or am I missing something with my implementation?

Hey @Pranav2612000,
As far as I know, this (from the article) is not the case on Netlify:

If your application makes subsequent calls to your Lambda function within 5 minutes, you can expect that the same container will be reused"

So it’s possible that your implementation would work directly on AWS but not Netlify.

1 Like