Managing Lambda versions

Each time a Lambda function is published, it gets assigned a sequential deployment number. You can invoke a particular version, and configure event sources to publish events to a particular Lambda deployment number, so Lambda makes it easy to roll deployments forwards and backwards and use multiple versions at the same time. In addition to sequential numeric versions, Lambda also supports aliases, named pointers to a particular numeric version. This makes it easy to use a single Lambda function for development, production and testing environments. For example, deploy a new Lambda version and mark it as development, then test it thoroughly, and then move the production alias to the same numeric version. You can configure event sources to invoke a particular alias, so after you declare the current version production, all production sources will immediately start invoking it without any additional configuration.

Detecting the current environment from code

Beware that aliases are just pointers to a numeric version. So, for example, you can publish version 10, assign the testing alias to it, test it, then reassign production alias to that version, and both testing and production then point to the same configuration. Lambda may choose to reuse the same container for subsequent calls. This means that a container that was previously used for testing might now get production requests. If you cache local configuration, such as database connections, make sure to avoid reusing the values from different contexts. You can easily detect the alias or version used to invoke the function from the Lambda context object from the last address segment:

exports.handler = function (event, context) {
  var environment = context.invokedFunctionArn.replace(/.*:/g,'');
}

Check out the Detecting Lambda Context example project for a full example.

Configuration for different environments

The easiest way to manage code in multiple environments is to make the code environment-independent, and manage environment-specific tasks with configuration (eg connection strings for databases etc). There are several good ways for achieving that:

exports.handler = function (event, context) {
var environment = context.invokedFunctionArn.replace(/.*:/g,''),
    config = require('./' + environment + '.json'); 
...

Here are some key considerations to help you choose the right way for configuring your environment:

Setting version aliases

You can set version aliases easily using AWS command line tools or Claudia. With AWS CLI tools, use aws lambda create-alias and aws lambda update-alias. If you changed any configuration or uploaded a new package, you may need to use aws lambda publish-version to publish a new numeric version before setting the alias.

Claudia helps to automate this, and keep the API gateway stages in sync with Lambda aliased. You can create a named alias by supplying --version to claudia create or claudia update and Claudia will automatically publish the version and associate a named alias with the current deployment number. For example, the following command will create a development version:

claudia create --region us-east-1 --version development

The next command will update the deployment and assign the testing alias to the new version:

claudia update --version testing

You can also re-assign a named alias to the last deployed version quickly. This is useful, for example, after you have finished testing and want to promote the current deployment to production without a full redeployment. Use:

claudia set-version --version production

Claudia will automatically create a new alias for the currently deployed version, or re-assign an existing alias to it. The big difference between set-version and update is that update causes a new deployment from your local file system, and set-version uses the last deployed version.

If your project includes an API Gateway definition, this will also create a new deployment of the web API, and create or re-assign an API Gateway stage, linking it directly to the Lambda alias. Each API Gateway stage has a unique URL prefix, so this makes it easy to invoke the right version of the API from client code. Claudia will print out the current version URL after each deployment, so you can easily copy it.

Using Lambda environment variables

You can set Lambda environment variables using AWS CLI tools with aws lambda create-function and aws lambda update-function-configuration. Remember to publish a new version after updating the configuration.

You can then access these variables from the standard Node.js process.env object.

exports.handler = function (event, context) {
	'use strict';
	context.succeed(process.env);
};

If you’re using a single function for different purposes (eg development, testing and production), remember that the same container might be reused for different aliases, and that the configuration of environment variables is tied to a numerical version, not an alias. To avoid nasty surprises, it’s best to select environment variables based on the currently executing alias (eg set both PRODUCTION_DB and TESTING_DB in the environment variables, then select the right one based on the executing context).

Claudia (since version 2.2.0) helps with setting the environment variables as well, and you can provide variables in two ways:

These options are available for claudia create, claudia update and claudia set-version. If you provide a new configuration to set-version, it will publish a new version after updating the configuration, not just reassign the alias to the last known version.

Check out the Environment Variables example project for a full example.

How to set stage variables for API Gateway

You can easily set API Gateway stage variables by using aws apigateway create-deployment and provide a list of variables.

If you use claudia-api-builder and API Gateway to invoke your function, you can then access those variables from the request.env key in the request processor.

Claudia can also help you automate the configuration process during deployment. Claudia will then enable users to configure the variable value either from the command line, or by prompting interactively during deployment. The syntax is:

api.addPostDeployConfig(stageVarName, prompt, configOption);

Here’s an example:

api.addPostDeployConfig('message', 'Enter a message:', 'custom-message');

In this case, message is the name of the stage variable (it will be available as request.env.message later). Enter a message: is the prompt that the users will see during deployment, and custom-message is the configuration option required to trigger the step. Running this command line will make Claudia ask you to enter the value:

claudia update --custom-message

Likewise, you can provide the value directly in the command line for unattended operation:

claudia update --custom-message Ping

To see this in action, see the Post-deploy configuration example project.

You can add several post-deployment steps to the same API, but note that the sequence of post-deployment steps is not guaranteed. Create isolated steps, don’t assume any particular order between them.

Did you like this tutorial? Get notified when we publish the next one.

Once a month, high value mailing list, no ads or spam. (Check out the past issues)