4

I'm planning to move my lambda function configuration from environment variables to DynamoDb since my lambda functions share configurations and also I don't want to redeploy my lambda functions each time a configuration changes (my config changes frequently and once they do I have to redeploy so many lambda functions).

But in order to improve the performance of my lambda functions and also to reduce the cost, I'm not going to load the configuration per each execution. Instead, I will load the config into a global variable and since global variables persist across executions (as long as the lambda function is warmed up) I can reuse the same config without accessing DynamoDb. Here's a sample code:

let config = null;
function getConfig() {
    if (config)
        return Promise.resolve(config);
    else {
        //Load config from DynamoDb and return it in form of a promise
    }
}

exports.handler = function(event, context, callback) {   
    getConfig()
        .then(config => {
            //Your code that makes use of config
        })
}

So far everything is fine. Now, consider the time that DynamoDb is updated with the new configuration. The warmed-up lambda functions will continue using the old config before they are brought down by AWS and face a cold-start.

What I want to do is to signal lambda functions and force them to flush their warmed-up lambda functions and start over each time the configuration changes. I know I can redeploy them which will do exactly what I wanted. But that's what exactly I was escaping from in the first place. So, what are my options?

Mehran
  • 15,593
  • 27
  • 122
  • 221

1 Answers1

1

You can use node-cache to achieve what you want to do. The values set by this library will persist if your function is warmed up, and will expire after the set TTL.

The usage is pretty straight forward, it will look something like this:

//try get from cache
cache.get(key, function(error, data) {
  if (error) {
    //handle error
  }
  if (!data) {
    //value not found in cache, so load values here
    //and then set using cache.set
    cache.set(key, data, TTL, function(error, success) {
      if (error) {
        //handle error
      }
      if (success) {
        //handle success
      }
    });
  }
  else {
    //value found in cache
  }
});

Note: Make sure you initialize the node-cache instance outside of your function handler

Deiv
  • 3,000
  • 2
  • 18
  • 30
  • the OP wants to FLUSH data, not reuse it. – Thales Minussi Mar 19 '19 at 15:34
  • Yes, you can do that by setting a TTL on the data, therefore flushing it every X seconds/minutes to refresh the data – Deiv Mar 19 '19 at 15:35
  • 1
    Thanks, I wasn't thinking of using a cache in node memory, for that I like your solution. But it does not really solve my problem since I was hoping to invalidate the cached data on-demand (when the data on DynamoDb is changed). Still, this could help if the lambda functions are long-lived and I want to make sure the cache is flushed every n-minutes (as an example). – Mehran Mar 19 '19 at 15:36
  • This won't work. OP wants all containers to read NEW values once something has been updated in DynamoDB – Thales Minussi Mar 19 '19 at 15:36
  • 1
    This will work if you have a set refresh delay that is acceptable for your use case, for ex 60 seconds TTL. The caching will save a lot of calls during those 60 seconds and will ensure when you update data, the Lambdas will refresh within a minute (and usually sooner, because it's a TTL from the moment the Lambda sets the value, so chances are high that it is already through a portion of it). If the requirement is having it update instantly, then unfortunately Lambda doesn't have anything like that (other than getting the value on each execution), caching is the only option that gets close. – Deiv Mar 19 '19 at 15:45