Jimlin Jimlin - 1 year ago 108
Node.js Question

Best Practices in Serverless Framework

I am new beginner in serverless framwork.
When study Best Practices in Serverless.

I have a question about "Initialize external services outside of your Lambda code".
How to implement it?
For example: Below code in handler.js

const getOneUser = (event, callback) => {
let response = null;
// validate parameters
if (event.accountid && process.env.SERVERLESS_SURVEYTABLE) {
let docClient = new aws.DynamoDB.DocumentClient();
let params = {
TableName: process.env.SERVERLESS_USERTABLE,
Key: {
accountid: event.accountid,
docClient.get(params, function(err, data) {
if (err) {
// console.error("Unable to get an item with the request: ", JSON.stringify(params), " along with error: ", JSON.stringify(err));
return callback(getDynamoDBError(err), null);
} else {
if (data.Item) { // got response
// compose response
response = {
accountid: data.Item.accountid,
username: data.Item.username,
email: data.Item.email,
role: data.Item.role,
return callback(null, response);
} else {
// console.error("Unable to get an item with the request: ", JSON.stringify(params));
return callback(new Error("404 Not Found: Unable to get an item with the request: " + JSON.stringify(params)), null);
// incomplete parameters
else {
return callback(new Error("400 Bad Request: Missing parameters: " + JSON.stringify(event)), null);

The question is that how to initial DynamoDB outside of my Lambda code.


Is below code optimized?


let survey = require('./survey');
module.exports.handler = (event, context, callback) => {
return survey.getOneSurvey({
accountid: event.accountid,
surveyid: event.surveyid
}, callback);


module.exports = (() => {
const getOneSurvey = (event, callback) {....
let docClient = new aws.DynamoDB.DocumentClient();

getOneSurvey : getOneSurvey,

Answer Source

Here's the quote in question:

Initialize external services outside of your Lambda code

When using services (like DynamoDB) make sure to initialize outside of your lambda code. Ex: module initializer (for Node), or to a static constructor (for Java). If you initiate a connection to DDB inside the Lambda function, that code will run on every invoke.

In other words, in the same file, but outside of -- before -- the actual handler code.

let docClient = new aws.DynamoDB...
const getOneUser = (event, callback) => {
  docClient.get(params, ...

When the container starts, the code outside the handler runs. When subsequent function invocations reuse the same container, you save resources and time by not instantiating the external services again. Containers are often reused, but each container only handles one concurrent request at a time, and how often they are reused and for how long is outside your control... Unless you update the function, in which case any existing containers will no longer be reused, because they'd have the old version of the function.

Your code will work as written, but isn't optimized.

The caveat in Node 4.3.2 is that some external services will keep the event loop from becoming empty, in which case you need to either take a different approach or allow lambda to not wait for an empty event loop before freezing the container, by setting context.callbackWaitsForEmptyEventLoop to false before calling the callback... but only do this if needed and only if you fully understand what it means. Setting it by default because some guy on the Internet said it was a good idea will potentially bring you mysterious bugs, later.