Navigation

Best Practices Connecting from 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.

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}
Give Feedback

On this page

  • Connection Examples