MongoDB connections from AWS Lambda MongoDB connections from AWS Lambda node.js node.js

MongoDB connections from AWS Lambda


AWS Lambda functions should be defined as stateless functions, so they can't hold state like a connection pool.

This issue was also raised in this AWS forum post. On Oct 5, 2015 AWS engineer Sean posted that you should not open and close connection on each request, by creating a pool on code initialization, outside of handler block. But two days later the same engineer posted that you should not do this.

The problem is that you don't have control over Lambda's runtime environment. We do know that these environments (or containers) are reused, as describes the blog post by Tim Wagner. But the lack of control can drive you to drain all your resources, like reaching a connection limit in your database. But it's up to you.

Instead of connecting to MongoDB from your lambda function you can use RESTHeart to access the database through HTTP. The connection pool to MongoDB is maintained by RESTHeart instead. Remember that in regards to performance you'll be opening a new HTTP connection to RESTHeart on each request, and not using a HTTP connection pool, like you could do in a tradicional application.


Restheart is a REST-based server that runs alongside MongoDB. It maps most CRUD operations in Mongo to GET, POST, etc., requests with extensible support when you need to write a custom handler (e.g., specialized geoNear, geoSearch query)


You should assume lambdas to be stateless but the reality is that most of the time the vm is simply frozen and does maintain some state. It would be stupid for Amazon to spin up a new process for every request so they often re-use the same process and you can take advantage of this to avoid thrashing connections.

To avoid connecting for every request (in cases where the lambda process is re-used):

  1. Write the handler assuming the process is re-used such that you connect to the database and have the lamba re-use the connection pool (the db promise returned from MongoClient.connect).

  2. In order for the lambda not to hang waiting for you to close the db connection, db.close(), after servicing a request tell it not wait for an empty event loop.

Example:

var db = MongoClient.connect(MongoURI);module.exports.targetingSpec = (event, context, callback) => {  context.callbackWaitsForEmptyEventLoop = false;  db.then((db) => {    // use db  });};

From the documentation about context.callbackWaitsForEmptyEventLoop:

callbackWaitsForEmptyEventLoop The default value is true. This property is useful only to modify the default behavior of the callback. By default, the callback will wait until the Node.js runtime event loop is empty before freezing the process and returning the results to the caller. You can set this property to false to request AWS Lambda to freeze the process soon after the callback is called, even if there are events in the event loop. AWS Lambda will freeze the process, any state data and the events in the Node.js event loop (any remaining events in the event loop processed when the Lambda function is called next and if AWS Lambda chooses to use the frozen process). For more information about callback, see Using the Callback Parameter.