Build a Twitter Leaderboard App: Redis, AWS Lambda


This is the next site post of a two-part collection that works by using a realistic software to reveal how to combine Redis with AWS Lambda. The first write-up was about the answer overview and deployment. Ideally, you were equipped to try out it out conclusion to finish. As promised, element two will deal with the infrastructure features (IaC to be unique) which are comprised of three (CDK) stacks (in the context of a single CDK Application).

I will supply a wander-by way of of the CDK code which is published in Go, thanks to the CDK Go assistance. AWS Cloud Advancement Kit (CDK) is all about IaC (Infrastructure-as-code).

Architecture of the Alternative

Just as a refresher, below is the significant-degree architecture of the remedy:

High-level architecture

Large-level architecture

Division of Architecture

The architecture is divided into two rational elements:

  1. The initial section handles tweet ingestion: A Lambda functionality fetches tweets (from Twitter), extracts hashtags for each and every tweet, and suppliers them in MemoryDB (in a Redis Sorted Established). This function gets invoked primarily based on a agenda centered on a rule in the CloudWatch set off.
  2. The 2nd component presents the leaderboard performance: This is nonetheless a further Lambda perform that provides an HTTP(s) endpoint (thanks to Lambda Functionality URL) to question the sorted set and extract the top 10 hashtags (leaderboard).

Expert services Overview

In this article is a fast overview of the services concerned in the solution:

  • Amazon MemoryDB for Redis: It is a sturdy, in-memory databases services that is appropriate with Redis, so empowering you to establish purposes making use of the exact same versatile and welcoming Redis details buildings, APIs, and instructions that they currently use right now.
  • Lambda Function URL is a somewhat new attribute (at the time of crafting this web site) that provides a committed HTTP(S) endpoint for your Lambda purpose. It is really helpful when all you will need is a one endpoint for your function (e.g., to provide as a webhook) and will not want to established up and configure an API Gateway.
  • As said previously, AWS Cloud Enhancement Package (CDK) is all about IaC (Infrastructure-as-code). It is a framework for defining cloud infrastructure in code and provisioning it by means of AWS CloudFormation. You can decide on from a list of supported programming languages (at the time of writing, this listing involves TypeScript, JavaScript, Python, Java, C#/.Net, and Go, in developer preview) to outline your infrastructure parts as code, just like you would with any other software!

CDK Code Walk By

The option is comprised of a few (CDK) Stacks (in the context of a single CDK Application).

  • The very first stack deploys a VPC (and also subnets, NAT gateway, and many others.), a MemoryDB for the Redis cluster, and a several stability groups.
  • The second stack deploys the to start with Lambda purpose which is accountable for ingesting tweet facts into Redis.
  • At last, the 3rd stack deploys the leaderboard Lambda perform. 

Notice that we could have included all the above as aspect of a solitary stack considering that this is a demo application. However, I wanted to reveal how you can leverage multiple stacks in just a single CDK application. For a a lot more complex generation infrastructure, it helps make sense to use a number of stacks in purchase to retain your sources decoupled and makes it much much easier to cope with and explanation about your CDK logic. 

Let us wander via the code, 1 stack at a time:

Be sure to notice that some of the code has been redacted/omitted for brevity – you can generally refer to full code in the GitHub repo.

1.  Start with the infrastructure stack.

stack := awscdk.NewStack(scope, &id, &sprops)
vpc = awsec2.NewVpc(stack, jsii.String("demo-vpc"), nil)

authInfo := map[string]interface"Sort": "password", "Passwords": []stringmemorydbPassword
user = awsmemorydb.NewCfnUser(stack, jsii.String("demo-memorydb-consumer"), &awsmemorydb.CfnUserPropsUserName: jsii.String("demo-user"), AccessString: jsii.String(accessString), AuthenticationMode: authInfo)
acl := awsmemorydb.NewCfnACL(stack, jsii.String("demo-memorydb-acl"), &awsmemorydb.CfnACLPropsAclName: jsii.String("demo-memorydb-acl"), UserNames: &[]*stringuser.UserName())

//snip .....

subnetGroup := awsmemorydb.NewCfnSubnetGroup(stack, jsii.String("demo-memorydb-subnetgroup"), &awsmemorydb.CfnSubnetGroupPropsSubnetGroupName: jsii.String("demo-memorydb-subnetgroup"), SubnetIds: &subnetIDsForSubnetGroup)

memorydbSecurityGroup = awsec2.NewSecurityGroup(stack, jsii.String("memorydb-demo-sg"), &awsec2.SecurityGroupPropsVpc: vpc, SecurityGroupName: jsii.String("memorydb-demo-sg"), AllowAllOutbound: jsii.Bool(accurate))

memorydbCluster = awsmemorydb.NewCfnCluster(//... particulars omitted)


twitterIngestFunctionSecurityGroup = awsec2.NewSecurityGroup(//... specifics omitted)
twitterLeaderboardFunctionSecurityGroup = awsec2.NewSecurityGroup(//... aspects omitted)

memorydbSecurityGroup.AddIngressRule(//... specifics omitted)
memorydbSecurityGroup.AddIngressRule(//... specifics omitted)

To summarize:

  • awsec2.NewVpc:  A one line of code is all it will take to create VPC and associated parts these types of as public and personal subnets, NAT gateways, and additional. Evaluate that in opposition to a regular CloudFormation template that you would will need to compose to get this performed!
  • We designed a Person (alongside with a password for authentication), ACL (Access Handle Record for authorization), and Subnet group for the MemoryDB cluster. Refer to them during cluster development with awsmemorydb.NewCfnCluster
  • We also produced the demanded protection groups. Their primary role is to let Lambda functions to accessibility MemoryDB. We specify specific Inbound guidelines to make that doable.
    • One particular for MemoryDB cluster
    • Just one each individual for both the Lambda capabilities

Notice: We are using an L1 construct for MemoryDB for Redis.

2.  The future stack deploys the tweets’ ingestion Lambda Perform.


memoryDBEndpointURL := fmt.Sprintf(

lambdaEnvVars := &map[string]*string"MEMORYDB_ENDPOINT": jsii.String(memoryDBEndpointURL), "MEMORYDB_Person": user.UserName(), "MEMORYDB_PASSWORD": jsii.String(getMemorydbPassword()), "TWITTER_API_Important": jsii.String(getTwitterAPIKey()), "TWITTER_API_Solution": jsii.String(getTwitterAPISecret()), "TWITTER_Access_TOKEN": jsii.String(getTwitterAccessToken()), "TWITTER_Access_TOKEN_Mystery": jsii.String(getTwitterAccessTokenSecret())

awslambda.NewDockerImageFunction(stack, jsii.String("lambda-memorydb-func"), &awslambda.DockerImageFunctionPropsFunctionName: jsii.String(tweetIngestionFunctionName), Surroundings: lambdaEnvVars, Timeout: awscdk.Duration_Seconds(jsii.Selection(20)), Code: awslambda.DockerImageCode_FromImageAsset(jsii.String(tweetIngestionFunctionPath), nil), Vpc: vpc, VpcSubnets: &awsec2.SubnetSelectionSubnets: vpc.PrivateSubnets(), SecurityGroups: &[]awsec2.ISecurityGrouptwitterIngestFunctionSecurityGroup)


It truly is rather easy as opposed to the past stack. We start off by defining the atmosphere variables required by our Lambda perform (which include Twitter API qualifications) and then deploy it as a Docker graphic.

For the functionality to be packaged as a Docker graphic, I utilized the Go:1.x foundation graphic, but you can take a look at other choices as properly. Throughout deployment, the Docker graphic is crafted regionally, pushed to a non-public ECR registry, and finally the Lambda perform is created: all this, with a handful of traces of code!

It’s worth checking the L2 construct (in alpha state at the time of producing) which helps make it even more simple to deploy Go functions applying CDK. You can refer to the documentation.

Notice that the MemoryDB cluster and protection team are quickly referred/appeared-up from the past stack (not re-established!).

3.  Finally, the 3rd stack requires treatment of the leaderboard Lambda perform. It’s really very similar to the previous a person, besides for the addition of the Lambda Perform URL (awslambda.NewFunctionUrl) which we use as the output for the stack:

memoryDBEndpointURL := fmt.Sprintf(

lambdaEnvVars := &map[string]*string"MEMORYDB_ENDPOINT": jsii.String(memoryDBEndpointURL), "MEMORYDB_USERNAME": person.UserName(), "MEMORYDB_PASSWORD": jsii.String(getMemorydbPassword())

purpose := awslambda.NewDockerImageFunction(stack, jsii.String("twitter-hashtag-leaderboard"), &awslambda.DockerImageFunctionPropsFunctionName: jsii.String(hashtagLeaderboardFunctionName), Atmosphere: lambdaEnvVars, Code: awslambda.DockerImageCode_FromImageAsset(jsii.String(hashtagLeaderboardFunctionPath), nil), Timeout: awscdk.Period_Seconds(jsii.Amount(5)), Vpc: vpc, VpcSubnets: &awsec2.SubnetSelectionSubnets: vpc.PrivateSubnets(), SecurityGroups: &[]awsec2.ISecurityGrouptwitterLeaderboardFunctionSecurityGroup)

funcURL := awslambda.NewFunctionUrl(stack, jsii.String("func-url"), &awslambda.FunctionUrlPropsAuthType: awslambda.FunctionUrlAuthType_NONE, Operate: purpose)

awscdk.NewCfnOutput(stack, jsii.String("Operate URL"), &awscdk.CfnOutputPropsPrice: funcURL.Url())

Which is all for this website article. I’ll shut out with backlinks to AWS Go CDK v2 references:

This concludes the two-aspect series. Keep tuned for extra and as constantly, pleased coding!


Please follow and like us:
Content Protection by