Using Amazon ElastiCache for Redis within a Lambda Function

Somebody who likes to code
Search for a command to run...

Somebody who likes to code
No comments yet. Be the first to comment.
In the previous post Deploying AWS Lambda Functions with AWS SAM, we saw how easy it is to deploy an AWS Lambda function with Amazon API Gateway. Today we want to complement it by using SNS and SQS as triggers for the Lambda function when dealing wit...
Google processes tens of thousands of code changes every day across a codebase of hundreds of millions of lines. The secret isn't magic tooling — it's a documented, principled approach to code review

Amazon Simple Notification Service (SNS) looks straightforward on the surface — publish a message, deliver it to subscribers — but the gap between a topic that "works in dev" and one that is productio

Amazon Simple Queue Service (SQS) is deceptively simple to get started with, but surprisingly easy to misconfigure in ways that cause silent message loss, runaway costs, duplicate processing storms, o

HTTP API is the right default choice for the majority of .NET serverless workloads. At 70% less cost than REST API, lower latency, and native JWT authorization, it covers most production requirements

AWS Lambda has become a cornerstone of modern serverless architectures, but writing a function that "just works" is very different from writing one that is performant, cost-effective, secure, and read

On this page
In a previous post, we reviewed how to access a non-public resource in a VPC from a Lambda function. Today we do the same but with a different Amazon resource, Redis:
Amazon Elasticache for Redis is a distributed in-memory data store that is built on open-source Redis. It works with Redis APIs, and standard Redis client libraries, and uses open Redis data formats. Amazon ElastiCache for Redis can be used as a cache environment for your cloud applications in AWS.
An Amazon ElastiCache Cluster (Redis).
Install AWS CLI.
Install the Amazon Lambda Templates (dotnet new -i Amazon.Lambda.Templates).
Install the Amazon Lambda Tools (dotnet tool install -g Amazon.Lambda.Tools).
Install AWS SAM CLI.
We will build an API to calculate a GUID value after a very expensive process. Redis will be used to store the value for 60 seconds using as a key a part of the request path. Run the following command to create the .NET projects and solution:
dotnet new lambda.EmptyFunction -n verySlowCalculationApi -o .
dotnet new sln -n aws-elasticache-sandbox
dotnet sln add --in-root src/verySlowCalculationApi
dotnet add src/verySlowCalculationApi package Amazon.Lambda.APIGatewayEvents
dotnet add src/verySlowCalculationApi package StackExchange.Redis
Open the solution and modify the Function.cs file with the following content:
public class Function
{
private IDatabase _database;
public Function()
{
var connectionString = Environment.GetEnvironmentVariable("REDIS_CONFIGURATION");
var connection = ConnectionMultiplexer.Connect(connectionString);
_database = connection.GetDatabase();
}
public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest input, ILambdaContext context)
{
var id = input.PathParameters["id"];
var value = string.Empty;
var cacheValue = await _database.StringGetAsync(id);
if(cacheValue.HasValue)
{
value = cacheValue;
}
else
{
value = await VeryExpensiveCalculation();
await _database.StringSetAsync(id, value, TimeSpan.FromSeconds(60), When.Always, CommandFlags.PreferMaster);
}
return new APIGatewayProxyResponse
{
Body = "{\"Value\":\""+ value + "\"}",
StatusCode = 200,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
public async Task<string> VeryExpensiveCalculation()
{
await Task.Delay(5000);
return Guid.NewGuid().ToString();
}
}
Create a template.yml file at the solution level:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
Slow API
Parameters:
Redis:
Type: String
Default: <REDIS_CONFIGURATION>
Description: Redis configuration
Vpc:
Type: String
Default: <REDIS_VPC>
Description: Redis Vpc
Subnet:
Type: String
Default: <REDIS_SUBNET>
Description: Redis Subnet
Globals:
Function:
Timeout: 60
MemorySize: 512
Runtime: dotnet6
Architectures:
- x86_64
Environment:
Variables:
REDIS_CONFIGURATION: !Ref Redis
Resources:
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: lambda security group
VpcId: !Ref Vpc
VerySlowFunction:
Type: AWS::Serverless::Function
Properties:
Handler: verySlowCalculationApi::verySlowCalculationApi.Function::FunctionHandler
CodeUri: ./src/verySlowCalculationApi/
VpcConfig:
SecurityGroupIds:
- !Ref LambdaSecurityGroup
SubnetIds:
- !Ref Subnet
Policies:
- AWSLambda_FullAccess
- AWSLambdaVPCAccessExecutionRole
Events:
ListPosts:
Type: Api
Properties:
Path: /{id}
Method: get
Outputs:
Api:
Description: "API Gateway endpoint URL"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/{id}"
To connect the Lambda function to the VPC, we need to do the following:
Assign the AWSLambdaVPCAccessExecutionRole and AWSLambda_FullAccess policies.
Create the LambdaSecurityGroup security group(inside our VPC) and use it in our Lambda function(SecurityGroupIds property).
Assign a subnet(the same subnet where our Redis cache lives) to the Lambda function(SubnetIds property)
Run sam build to build the application, and then sam deploy --guided, the command will guide you through the deployment. One thing to notice is that, by default, the Redis is not designed to be public. You can follow this article to achieve it, but we recommend using a local instance to test your lambda function before deploying it. All the code is available here. Thanks, and happy coding.