AWS Lambda Global Variables


The Good the Bad & the Ugly – AWS Service Deep Dive

When building a lambda, we have the option to put variables outside of the handler. Anything that we store outside of the handler is accessible to all future lambda invocations that use that container. This can be used very well or can cause hard-to-find bugs. This article and video will help you understand this global variable so you can use them deliberately and correctly.

Correct Use of Global Variables

You can use global variables to cache responses from APIs or databases.

let cachedData = {};
    
    
    exports.handler = async (event) => {
        if (cachedData && cachedData.expiresOn > Date.now() ) {
             const response = {
                statusCode: 200,
                body: `The weather is ${cachedData.weather} and it is ${cachedData.temperature} decrees Celcius`,
            };
            return response;
        }
        
        const { weather, temperature } = await fakeWeatherAPIRequest(event);
        
        cachedData = {
            weather,
            temperature,
            expiresOn: Date.now() + 30 * 1000 
        };
        
        const response = {
            statusCode: 200,
            body: `The weather is ${weather} and it is ${temperature} decrees Celcius`
        };
        return response;
    };
    
    
    const fakeWeatherAPIRequest = async (event) => {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve({
                    weather: 'sunny',
                    temperature: '15'
                });
            }, 3000);
        });
    };

Just make sure the thing that you are caching isn’t changing very quickly and that you the customer aren’t passing up a parameter that would make your cached data wrong.

There are libraries such as lambda-local-cache which do a lot of the heavy lifting and allow you to cache a data locally.

When Global Variables Cause Bugs

If you are relying on the data in a global variable to be consistent then you need to be very careful. If you ever reference the value of one of those variables and then change that value, it can cause bugs in future invocations of that lambda.

let config = {
        minimumScore: 50,
    };
    
    exports.handler = async (event) => {
        
        const { score, mode } = event;
        
        let minimumScore = config.minimumScore
        
        if ( mode === 'hard') {
            minimumScore = 25;
        }
        
        if (score < minimumScore ){
            return `You need to score higher to get onto the ${mode} leaderboard. ${score}/${minimumScore}`;
        }
        
        return `Congratuations! You made it onto the ${mode} leaderboard. ${score}/${minimumScore}`;
    };
    

If we invoke this lambda with a user like playing on easy mode with a score of 30, we would expect the response to be: You need to score higher to get onto the easy leaderboard. 30/50. This is what you’d expect from reading the code.

If you then have a player on hard mode with a score of 45 you’d also expect a result of Congratuations! You made it onto the hard leaderboard. 45/25.

When the first player submits a new score of 32 on the easy mode to the same lambda we get a bug. Congratuations! You made it onto the easy leaderboard. 32/25. There are a few things wrong with this. The player only got 32 so didn’t beat the easy leaderboard level of 50. The message says 32/25 that 25 isn’t the easy score to beat.

This is because when the player on hard submitted the score, this line of code ran: minimumScore = 25;. This variable references the global variable which has now been set the global minimum score to 25. When the easy player submits a score of 32, the global minimum is 25, hence the congratulations message.

This mutation of the global variable can cause a range of bugs like this, but now you know about it you’ll be better equipped to find it and fix it.

Sam Williams

Sam is a Serverless Obsessive who runs Complete Coding, helping developers learn Serverless and companies make the most of the competitive advantage that Serverless gives them. Previous projects include: - Designing a chat platform that currently resolves over 250,000 customer inquiries a month for international retailers and local government - Architecting a backend system to support a 3D clothing visualisation tool - Building a solution to manage millions of dollars of communication software - Designing a "Video Editing in the Cloud" platform, enabling everyone from movie studios to indie film makers to harness the power of the Cloud - without needing to be cloud experts. - Launching a profitable Serverless Startup in under 30 days He has also been teaching cloud-based software development for 5 years and has taught Serverless development to thousands of people. The Complete Coding Youtube channel now has over 15,000 subscribers and over 1 million views

Recent Posts