Docs Menu

Manage Connections with AWS Lambda

On this page

  • Connection Examples

Use the following best practices to properly manage connections between AWS Lambda and Atlas:

  • Define the client to the MongoDB server outside the AWS Lambda handler function.

    Don't define a new MongoClient object each time you invoke your function. Doing so causes the driver to create a new database connection with each function call. This can be expensive and can result in your application exceeding database connection limits. As an alternative, do the following:

    1. Create the MongoClient object once.
    2. Store the object so your function can reuse the MongoClient across function invocations.

    The Connection Example reuses existing database connections to speed up communication with the database and keep connection counts to the database at a reasonable level with respect to application traffic.

  • If your handler takes a callback as its last argument, set the callbackWaitsForEmptyEventLoop property on the AWS Lambda Context object to false.

    context.callbackWaitsForEmptyEventLoop = false;

    This allows a Lambda function to return its result to the caller without requiring that the MongoDB database connection be closed. Setting this property is not applicable for async handlers.

  • Restrict network access to your Atlas cluster.

    Connect to your Atlas cluster over private networking using a Network Peering connection between your Atlas cluster and your AWS Lambda function, or, alternatively, a private endpoint, so that you can allow only private IP addresses to your IP access list.

    If private networking is not an option, consider connecting to your Atlas cluster via a NAT gateway with a mapped Elastic IP address. Otherwise, you must allow all IP addresses (0.0.0.0/0) to access your service cluster.

  • Set Up Unified AWS Access and use AWS IAM authentication where possible.

    You can connect to your Atlas clusters using AWS IAM roles instead of hardcoding your credentials in Lambda. Hardcoded credentials are viewable by anyone who accesses your AWS Lambda environment, which can pose a security risk. With AWS IAM authentication, Atlas accesses AWS Lambda through an assumed IAM role, so you don't need credentials in your connection strings.

    Atlas supports AWS IAM authentication for clusters running MongoDB version 4.4 or higher. We strongly advise using AWS IAM authentication for Lambda connections if your cluster meets the requirements.

    To use AWS IAM authentication, Set Up Unified AWS Access.

    Note

    For the connection examples on this page, you can use AWS IAM authentication instead of hardcoded credentials by doing the following:

    1. Set Up Unified AWS Access
    2. In the first Node.js example, replace const { MongoClient } = require('mongodb'); with the following lines of code:

      index.js
      1const MONGODB_CONNECTION_STRING = new URL(process.env.MONGODB_URI);
      2MONGODB_CONNECTION_STRING.username = process.env.AWS_ACCESS_KEY_ID;
      3MONGODB_CONNECTION_STRING.password = encodeURIComponent(process.env.AWS_SECRET_ACCESS_KEY);
      4MONGODB_CONNECTION_STRING.searchParams.set('authSource', '$external');
      5MONGODB_CONNECTION_STRING.searchParams.set('authMechanism', 'AWS_SESSION_TOKEN:' + encodeURIComponent(process.env.AWS_SESSION_TOKEN));
    3. In the first Node.js example, replace process.env.MONGODB_URI with MONGODB_CONNECTION_STRING.toString()

This section includes examples for two approaches:

  • In the first Node.js example, the index.js file shows how to reuse Mongoclient.connect across function invocations.
  • In the second Node.js example, the index.js and mongodb-client.js files show how to isolate the call to MongoClient.connect into its own module so that the connections can be reused across functions. Use this approach if you package multiple logical functions together in a single Lambda handler function.

The following example shows the best practice of defining the MongoClient.connect function in your application's Node.js code outside the handler so it can be reused across function invocations.

index.js
1"use strict";
2
3// Import the dependency.
4const { MongoClient } = require('mongodb');
5
6// Create a module-scoped MongoClient promise.
7// CRITICAL: You must call connect() outside the handler so that the client
8// can be reused across function invocations.
9let client = new MongoClient(process.env.MONGODB_URI,
10 { useNewUrlParser: true, useUnifiedTopology: true });
11const clientPromise = client.connect();
12
13// Handler
14module.exports.handler = async function(event, context) {
15
16// Get the MongoClient by calling await on the promise.
17// Because this is a promise, it will only resolve once.
18client = await clientPromise;
19
20// Use the client to return the name of the connected database.
21return client.db().databaseName;
22}

Some serverless frameworks that run on top of Lambda allow for multiple logical functions to be packaged together in a single Lambda handler function. If your application runs multiple functions within the same Lambda process, we recommend isolating the call to the MongoClient.connect function into its own module so that the connections can be reused across functions.

In the following code examples:

  • mongo-client.js organizes the MongoClient.connect function into its own module (mongo-client).
  • index.js imports that module and uses it to connect.
mongodb-client.js
1"use strict";
2
3// Import the dependency.
4const { MongoClient } = require('mongodb');
5
6// Export a module-scoped MongoClient promise. By doing this in a separate
7// module, the client can be shared across functions.
8const client = new MongoClient(process.env.MONGODB_URI,
9 { useNewUrlParser: true, useUnifiedTopology: true });
10module.exports = client.connect();
index.js
1"use strict";
2
3// Import the dependency.
4const clientPromise = require('./mongodb-client');
5
6// Handler
7module.exports.handler = async function(event, context) {
8
9 // Get the MongoClient by calling await on the connection promise. Because
10 // this is a promise, it will only resolve once.
11 const client = await clientPromise;
12
13 // Use the connection to return the name of the connected database.
14 return client.db().databaseName;
15}
←  Test FailoverTroubleshoot Connection Issues →
Give Feedback
© 2022 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2022 MongoDB, Inc.