Skip to content

Instantly share code, notes, and snippets.

@hassy
Last active September 19, 2022 17:20
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hassy/eaea5a958067211f2fed02ead13c2678 to your computer and use it in GitHub Desktop.
Save hassy/eaea5a958067211f2fed02ead13c2678 to your computer and use it in GitHub Desktop.
Different behavior of context.succeed() vs callback() in AWS Lambda
//
// Lambda's timeout needs to be >5 seconds, 10 should do
//
var startedAt = new Date();
var interval = setInterval(function () {
console.log(startedAt, new Date());
}, 1000);
exports.handler = function (event, context, callback) {
setTimeout(function () {
console.log('returning');
// v1:
return callback(null);
// v2:
// return context.succeed();
}, 5000);
};
@hassy
Copy link
Author

hassy commented Jun 2, 2016

With v1, the lambda times out.

With v2, the lambda succeeds.

unref()ing the interval makes v1 work as expected.

The change in behavior is not documented in the official docs, and context.succeed / fail aren't documented anymore, probably meaning that they will be deprecated along with the 0.10 runtime in October 2016.

@hassy
Copy link
Author

hassy commented Jun 2, 2016

setting context.callbackWaitsForEmptyEventLoop to false makes the callback behave like context.succeed() wrt to waiting for active handles - http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html

@swhite24
Copy link

Ah, thanks for this!

@JulienBlancher
Copy link

Helpful, thanks !

Copy link

ghost commented Feb 17, 2017

I'm running a postgres query function, I want to fire and forget the query, not wait for the results. I'm using the 'pg' package from npmjs. Can I use this to force a return?

@murali129
Copy link

Thanks, this is the only place where i found the difference between context() and callback(), it was not obvious for me to guess that context() will terminate the lambda function where as callback will still run the lambda, but I don't find any use case of using callback over context, please feed me with an example.

@kidsil
Copy link

kidsil commented Jun 2, 2017

context.callbackWaitsForEmptyEventLoop = false;
callback(null, {result: result});

works for me

@tjwebb
Copy link

tjwebb commented Jul 5, 2017

@bardiaafshin yes

@ashish314
Copy link

ashish314 commented Jul 25, 2017

I am facing this same issue of callback not getting called.
setting context.callbackWaitsForEmptyEventLoop to false is an option but according to this post it may lead to unpredicted
behaviour.
https://forums.aws.amazon.com/thread.jspa?messageID=755419

@omarshibli
Copy link

Thanks a lot, very helpful.

@slaughtr
Copy link

Even with callbackWaitsForEmptyEventLoop set to false so that callback() doesn't timeout the function, I can't figure out a reason specifically to use callback(null, result)/(err) over context.succeed()/fail(). The syntax is less clear AND you have to change settings for it to work properly (and apparently doing so may cause unexpected behavior on the next invocation - unacceptable in a production environment).

Am I missing something? Is there a real reason for me to change all my context.succeed()/fail() calls to callback()? Fear of deprecation is the only thing that comes to mind.

@alexcasalboni
Copy link

@slaughtr imho, callbacks are a more natural way of doing it in Node.js since many frameworks/libraries already manage callbacks natively. It allows you to write more general/reusable code in your functions. On the other hand, using context means that every piece of your code must be aware of its existence. And well, the same holds for your unit tests.

In other words, there is "no technical advantage" besides coding style, conventions, reusability, and maintainability.

@DaVincii
Copy link

The nodejs event loop in your case may not be empty that's why the callback function doesn't work and when you set callbackWaitsForEmptyEventLoop= false, the event loop is not into consideration and the function is terminated straight away.

This may be happening because of the open connections to databases or waiting on some other I/O operation which is not letting the event loop to go empty.

@rodrigomf24
Copy link

@DaVincii is right, I can use callback() and it completes the request as long as there's no other connection/process hanging, in my case the connection to the db was still open so my lambda would timeout and never complete the request, after closing the client connection it resolved as expected.

@lfreneda
Copy link

same as @rodrigomf24, I forgot my db connection open.. after closing it resolved as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment