Lambda function A/B Testing with .NET and Function URLs

Want to talk with other .NET on AWS developers, ask questions, and share what you know? Join us on Slack!

Introduction

This post shows how to perform some simple A/B testing with Lambda functions. The functions will be invoked by via a Function URL.

In a recent post, I covered Lambda function versions, it is not required reading for this post, but I won’t be explaining it again here.

The aliases feature of Lambda allows you to assign one or more versions of a function to an alias, and you can choose the percentage of requests that are routed to each version.

In this example, you will deploy two versions of the function, one stable and one experimental. Then assign those versions to an alias. Finally, assign a Function URL to the alias.

1. Create and deploy the function

Follow steps 1-6 in this post to create a Lambda function that can handle HTTPS requests, using the name LambdaABTestingFunctionUrl instead of SimpleLambdaWithFunctionUrl.

But change the FunctionHandler(..) method to -

public APIGatewayHttpApiV2ProxyResponse FunctionHandler(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context)
{
    var response = new APIGatewayHttpApiV2ProxyResponse
    {
        StatusCode = (int)HttpStatusCode.OK,
        Body =  $"Stable function",
        Headers = new Dictionary<string, string> { { "Content-Type", "text/plain" } }
    };
        
    return response;
}

You should now have a Lambda function that can be invoked by a Function URL.

2. Create a stable version of the function

Create a new version of the Lambda function and give it the description “Stable” -

aws lambda publish-version --function-name LambdaABTestingFunctionUrl --description Stable

In the output of the command you will see a version number, note this as the version number of the stable version. It should be version 1.

3. Update the deployed function

Update the FunctionHandler(..) method, changing the text assigned to the body of the response -

Body =  $"Experimental function",

Deploy this using -

dotnet lambda deploy-function LambdaABTestingFunctionUrl

This does not overwrite the stable version.

4. Deploy the experimental version

aws lambda publish-version --function-name LambdaABTestingFunctionUrl --description Experimental

In the output of the command you will see a version number, note this as the version number of the experimental version. It should be version 2.

You now have two versions of the function.

5. Create an alias

If you are using PowerShell use -

aws lambda create-alias --function-name LambdaABTestingFunctionUrl --name ABTest --function-version 1 --routing-config AdditionalVersionWeights=
'{"2"=0.5}'

If you are using Command Prompt or Bash use -

aws lambda create-alias --function-name LambdaABTestingFunctionUrl --name ABTest --function-version 1 --routing-config AdditionalVersionWeights={"2"=0.5}

You will see output that looks like -

{
    "AliasArn": "arn:aws:lambda:us-east-1:xxxxxxxxxxx:function:LambdaABTestingFunctionUrl:ABTest",
    "Name": "ABTest",
    "FunctionVersion": "1",
    "Description": "",
    "RoutingConfig": {
        "AdditionalVersionWeights": {
            "2": 0.5
        }
    },
    "RevisionId": "459ef2f2-3843-4ea7-a1a7-eff1e410eca9"
}

Almost there, now all that is needed is to create a Function URL for the alias.

6. Create a Function URL for the alias

Create a Function URL for the alias -

aws lambda create-function-url-config --function-name LambdaABTestingFunctionUrl:ABTest --auth-type NONE

You will get output that looks like -

{
    "FunctionUrl": "https://xxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.us-east-1.on.aws/",
    "FunctionArn": "arn:aws:lambda:us-east-1:xxxxxxxxxxx:function:LambdaABTestingFunctionUrl:ABTest",
    "AuthType": "NONE",
    "CreationTime": "2022-08-27T14:18:32.121393Z"
}

Note that the FunctionUrl here will be different than the one you created in step 1. This is because the Function URL is for the alias.

Then add the resource-based policy to allow the Function URL to invoke the Lambda function-

aws lambda add-permission --function-name LambdaABTestingFunctionUrl:ABTest --statement-id AuthNone --action lambda:InvokeFunctionUrl --principal * --function-url-auth-type NONE

7. Test it out

Open the URL in a browser, and keep reloading it. You should see that you invoke the stable version sometimes, and the experimental version sometimes.

comments powered by Disqus

Related