ElastiCache Caching Layer
AWS architecture template · SAA-C03: API Gateway → Lambda → ElastiCache Redis + RDS (cache-aside pattern)
ElastiCache Caching Layer is a free AWS architecture template built with API Gateway, CloudWatch, ElastiCache, IAM, Lambda and RDS. Open it in TheArchitect to edit the diagram, estimate monthly cost, and export the CloudFormation or Terraform that deploys it.
AWS services in this template
- API Gateway
- CloudWatch
- ElastiCache
- IAM
- Lambda
- RDS
Deployment notes
Deploy-ready
- Deploys VPC Lambda with cache-aside logic, ElastiCache Redis cluster, RDS PostgreSQL, and a cache hit rate alarm.
Generated CloudFormation — 38 resources
| Logical ID | Resource type |
|---|---|
| APIGatewayapigateway | AWS::ApiGateway::RestApi |
| CacheLayerVPC10100016vpc | AWS::EC2::VPC |
| CacheLayerVPC10100016vpcedgewebsgSecurityGroup | AWS::EC2::SecurityGroup |
| CacheLayerVPC10100016vpcappruntimesgSecurityGroup | AWS::EC2::SecurityGroup |
| CacheLayerVPC10100016vpcappruntimesgSecurityGroupIngressRule | AWS::EC2::SecurityGroupIngress |
| CacheLayerVPC10100016vpcworkersgSecurityGroup | AWS::EC2::SecurityGroup |
| CacheLayerVPC10100016vpcdatastoresgSecurityGroup | AWS::EC2::SecurityGroup |
| CacheLayerVPC10100016vpcdatastoresgSecurityGroupIngressRule | AWS::EC2::SecurityGroupIngress |
| CacheLayerVPC10100016vpccontrolplanesgSecurityGroup | AWS::EC2::SecurityGroup |
| CacheLayerVPC10100016vpcPublicSubnet1 | AWS::EC2::Subnet |
| CacheLayerVPC10100016vpcPublicSubnet2 | AWS::EC2::Subnet |
| CacheLayerVPC10100016vpcPrivateSubnet1 | AWS::EC2::Subnet |
| CacheLayerVPC10100016vpcPrivateSubnet2 | AWS::EC2::Subnet |
| CacheLayerVPC10100016vpcPrivateSubnet3 | AWS::EC2::Subnet |
| CacheLayerVPC10100016vpcPrivateSubnet4 | AWS::EC2::Subnet |
| CacheLayerVPC10100016vpcInternetGateway | AWS::EC2::InternetGateway |
| CacheLayerVPC10100016vpcGatewayAttachment | AWS::EC2::VPCGatewayAttachment |
| CacheLayerVPC10100016vpcPublicRouteTable | AWS::EC2::RouteTable |
| CacheLayerVPC10100016vpcPublicRoute | AWS::EC2::Route |
| CacheLayerVPC10100016vpcPublicSubnet1RTA | AWS::EC2::SubnetRouteTableAssociation |
| CacheLayerVPC10100016vpcPublicSubnet2RTA | AWS::EC2::SubnetRouteTableAssociation |
| CacheLayerVPC10100016vpcNatEIP | AWS::EC2::EIP |
| CacheLayerVPC10100016vpcNatGateway | AWS::EC2::NatGateway |
| CacheLayerVPC10100016vpcPrivateRouteTable | AWS::EC2::RouteTable |
| CacheLayerVPC10100016vpcPrivateRoute | AWS::EC2::Route |
| CacheLayerVPC10100016vpcPrivateSubnet1RTA | AWS::EC2::SubnetRouteTableAssociation |
| CacheLayerVPC10100016vpcPrivateSubnet2RTA | AWS::EC2::SubnetRouteTableAssociation |
| CacheLayerVPC10100016vpcPrivateSubnet3RTA | AWS::EC2::SubnetRouteTableAssociation |
| CacheLayerVPC10100016vpcPrivateSubnet4RTA | AWS::EC2::SubnetRouteTableAssociation |
| CacheLayerVPC10100016vpcDbSubnetGroup | AWS::RDS::DBSubnetGroup |
| CacheLayerVPC10100016vpcCacheSubnetGroup | AWS::ElastiCache::SubnetGroup |
| CacheAsideLambdalambda | AWS::Lambda::Function |
| LambdaRoleiam | AWS::IAM::Role |
| RedisCacheelasticache | AWS::ElastiCache::CacheCluster |
| PostgreSQLDBrds | AWS::RDS::DBInstance |
| CacheHitAlarmcloudwatch | AWS::CloudWatch::Alarm |
| RedisCacheelasticacheIngressSG | AWS::EC2::SecurityGroup |
| PostgreSQLDBrdsIngressSG | AWS::EC2::SecurityGroup |
View the full CloudFormation template
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Generated by TheArchitect — https://www.thecloudarchitect.dev",
"Metadata": {
"TheArchitect": {
"Edges": [
{
"From": "LambdaRoleiam",
"To": "CacheAsideLambdalambda",
"Label": "role"
},
{
"From": "CacheAsideLambdalambda",
"To": "RedisCacheelasticache",
"Label": "check cache"
},
{
"From": "CacheAsideLambdalambda",
"To": "PostgreSQLDBrds",
"Label": "fallback SQL"
}
]
}
},
"Resources": {
"APIGatewayapigateway": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Name": "saa-cached-api",
"Description": "REST API with ElastiCache cache-aside pattern.",
"EndpointConfiguration": {
"Types": [
"REGIONAL"
]
}
}
},
"CacheLayerVPC10100016vpc": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.10.0.0/16",
"EnableDnsHostnames": true,
"EnableDnsSupport": true,
"Tags": [
{
"Key": "Name",
"Value": "saa-cache-vpc"
}
]
}
},
"CacheLayerVPC10100016vpcedgewebsgSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupName": "edge-web-sg",
"GroupDescription": "Allow HTTPS from the internet to public load balancers",
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"Tags": [
{
"Key": "Name",
"Value": "edge-web-sg"
}
],
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": 443,
"ToPort": 443,
"CidrIp": "0.0.0.0/0"
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "-1",
"CidrIp": "0.0.0.0/0"
}
]
}
},
"CacheLayerVPC10100016vpcappruntimesgSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupName": "app-runtime-sg",
"GroupDescription": "Allow application traffic from the edge tier",
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"Tags": [
{
"Key": "Name",
"Value": "app-runtime-sg"
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "-1",
"CidrIp": "0.0.0.0/0"
}
]
}
},
"CacheLayerVPC10100016vpcappruntimesgSecurityGroupIngressRule": {
"Type": "AWS::EC2::SecurityGroupIngress",
"Properties": {
"GroupId": {
"Ref": "CacheLayerVPC10100016vpcappruntimesgSecurityGroup"
},
"IpProtocol": "tcp",
"FromPort": 80,
"ToPort": 80,
"SourceSecurityGroupId": {
"Ref": "CacheLayerVPC10100016vpcedgewebsgSecurityGroup"
}
}
},
"CacheLayerVPC10100016vpcworkersgSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupName": "worker-sg",
"GroupDescription": "Private worker runtime egress only",
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"Tags": [
{
"Key": "Name",
"Value": "worker-sg"
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "-1",
"CidrIp": "0.0.0.0/0"
}
]
}
},
"CacheLayerVPC10100016vpcdatastoresgSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupName": "data-store-sg",
"GroupDescription": "Allow PostgreSQL from application runtimes",
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"Tags": [
{
"Key": "Name",
"Value": "data-store-sg"
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "-1",
"CidrIp": "0.0.0.0/0"
}
]
}
},
"CacheLayerVPC10100016vpcdatastoresgSecurityGroupIngressRule": {
"Type": "AWS::EC2::SecurityGroupIngress",
"Properties": {
"GroupId": {
"Ref": "CacheLayerVPC10100016vpcdatastoresgSecurityGroup"
},
"IpProtocol": "tcp",
"FromPort": 5432,
"ToPort": 5432,
"SourceSecurityGroupId": {
"Ref": "CacheLayerVPC10100016vpcappruntimesgSecurityGroup"
}
}
},
"CacheLayerVPC10100016vpccontrolplanesgSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupName": "control-plane-sg",
"GroupDescription": "Private EKS control plane attachment group",
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"Tags": [
{
"Key": "Name",
"Value": "control-plane-sg"
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "-1",
"CidrIp": "0.0.0.0/0"
}
]
}
},
"CacheLayerVPC10100016vpcPublicSubnet1": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"CidrBlock": "10.10.1.0/24",
"AvailabilityZone": "us-east-1a",
"MapPublicIpOnLaunch": true,
"Tags": [
{
"Key": "Name",
"Value": "public-edge-a"
}
]
}
},
"CacheLayerVPC10100016vpcPublicSubnet2": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"CidrBlock": "10.10.2.0/24",
"AvailabilityZone": "us-east-1b",
"MapPublicIpOnLaunch": true,
"Tags": [
{
"Key": "Name",
"Value": "public-edge-b"
}
]
}
},
"CacheLayerVPC10100016vpcPrivateSubnet1": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"CidrBlock": "10.10.11.0/24",
"AvailabilityZone": "us-east-1a",
"MapPublicIpOnLaunch": false,
"Tags": [
{
"Key": "Name",
"Value": "private-app-a"
}
]
}
},
"CacheLayerVPC10100016vpcPrivateSubnet2": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"CidrBlock": "10.10.12.0/24",
"AvailabilityZone": "us-east-1b",
"MapPublicIpOnLaunch": false,
"Tags": [
{
"Key": "Name",
"Value": "private-app-b"
}
]
}
},
"CacheLayerVPC10100016vpcPrivateSubnet3": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"CidrBlock": "10.10.21.0/24",
"AvailabilityZone": "us-east-1a",
"MapPublicIpOnLaunch": false,
"Tags": [
{
"Key": "Name",
"Value": "private-data-a"
}
]
}
},
"CacheLayerVPC10100016vpcPrivateSubnet4": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"CidrBlock": "10.10.22.0/24",
"AvailabilityZone": "us-east-1b",
"MapPublicIpOnLaunch": false,
"Tags": [
{
"Key": "Name",
"Value": "private-data-b"
}
]
}
},
"CacheLayerVPC10100016vpcInternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
"Tags": [
{
"Key": "Name",
"Value": "saa-cache-vpc-igw"
}
]
}
},
"CacheLayerVPC10100016vpcGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"InternetGatewayId": {
"Ref": "CacheLayerVPC10100016vpcInternetGateway"
}
}
},
"CacheLayerVPC10100016vpcPublicRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"Tags": [
{
"Key": "Name",
"Value": "saa-cache-vpc-public-rt"
}
]
}
},
"CacheLayerVPC10100016vpcPublicRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": [
"CacheLayerVPC10100016vpcGatewayAttachment"
],
"Properties": {
"RouteTableId": {
"Ref": "CacheLayerVPC10100016vpcPublicRouteTable"
},
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": {
"Ref": "CacheLayerVPC10100016vpcInternetGateway"
}
}
},
"CacheLayerVPC10100016vpcPublicSubnet1RTA": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "CacheLayerVPC10100016vpcPublicSubnet1"
},
"RouteTableId": {
"Ref": "CacheLayerVPC10100016vpcPublicRouteTable"
}
}
},
"CacheLayerVPC10100016vpcPublicSubnet2RTA": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "CacheLayerVPC10100016vpcPublicSubnet2"
},
"RouteTableId": {
"Ref": "CacheLayerVPC10100016vpcPublicRouteTable"
}
}
},
"CacheLayerVPC10100016vpcNatEIP": {
"Type": "AWS::EC2::EIP",
"DependsOn": [
"CacheLayerVPC10100016vpcGatewayAttachment"
],
"Properties": {
"Domain": "vpc"
}
},
"CacheLayerVPC10100016vpcNatGateway": {
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": {
"Fn::GetAtt": [
"CacheLayerVPC10100016vpcNatEIP",
"AllocationId"
]
},
"SubnetId": {
"Ref": "CacheLayerVPC10100016vpcPublicSubnet1"
},
"Tags": [
{
"Key": "Name",
"Value": "saa-cache-vpc-nat"
}
]
}
},
"CacheLayerVPC10100016vpcPrivateRouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
},
"Tags": [
{
"Key": "Name",
"Value": "saa-cache-vpc-private-rt"
}
]
}
},
"CacheLayerVPC10100016vpcPrivateRoute": {
"Type": "AWS::EC2::Route",
"Properties": {
"RouteTableId": {
"Ref": "CacheLayerVPC10100016vpcPrivateRouteTable"
},
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "CacheLayerVPC10100016vpcNatGateway"
}
}
},
"CacheLayerVPC10100016vpcPrivateSubnet1RTA": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet1"
},
"RouteTableId": {
"Ref": "CacheLayerVPC10100016vpcPrivateRouteTable"
}
}
},
"CacheLayerVPC10100016vpcPrivateSubnet2RTA": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet2"
},
"RouteTableId": {
"Ref": "CacheLayerVPC10100016vpcPrivateRouteTable"
}
}
},
"CacheLayerVPC10100016vpcPrivateSubnet3RTA": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet3"
},
"RouteTableId": {
"Ref": "CacheLayerVPC10100016vpcPrivateRouteTable"
}
}
},
"CacheLayerVPC10100016vpcPrivateSubnet4RTA": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet4"
},
"RouteTableId": {
"Ref": "CacheLayerVPC10100016vpcPrivateRouteTable"
}
}
},
"CacheLayerVPC10100016vpcDbSubnetGroup": {
"Type": "AWS::RDS::DBSubnetGroup",
"Properties": {
"DBSubnetGroupDescription": "Private subnets for saa-cache-vpc",
"SubnetIds": [
{
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet1"
},
{
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet2"
},
{
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet3"
},
{
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet4"
}
],
"Tags": [
{
"Key": "Name",
"Value": "saa-cache-vpc-db-subnet-group"
}
]
}
},
"CacheLayerVPC10100016vpcCacheSubnetGroup": {
"Type": "AWS::ElastiCache::SubnetGroup",
"Properties": {
"Description": "Private subnets for saa-cache-vpc",
"SubnetIds": [
{
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet1"
},
{
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet2"
},
{
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet3"
},
{
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet4"
}
],
"Tags": [
{
"Key": "Name",
"Value": "saa-cache-vpc-cache-subnet-group"
}
]
}
},
"CacheAsideLambdalambda": {
"Type": "AWS::Lambda::Function",
"DependsOn": [
"LambdaRoleiam"
],
"Properties": {
"Runtime": "nodejs20.x",
"Handler": "index.handler",
"MemorySize": 512,
"Architectures": [
"arm64"
],
"Timeout": 30,
"Description": "Implements cache-aside: checks Redis, falls back to RDS on miss.",
"VpcConfig": {
"SubnetIds": [
{
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet1"
},
{
"Ref": "CacheLayerVPC10100016vpcPrivateSubnet2"
}
],
"SecurityGroupIds": [
{
"Ref": "CacheLayerVPC10100016vpcappruntimesgSecurityGroup"
}
]
},
"Environment": {
"Variables": {
"APP_ENV": "demo",
"LOG_LEVEL": "info"
}
},
"TracingConfig": {
"Mode": "Active"
},
"Code": {
"ZipFile": "exports.handler = async (event) => ({ statusCode: 200, body: JSON.stringify({ ok: true, requestId: event.requestContext?.requestId || 'demo' }) });"
},
"Role": {
"Fn::GetAtt": [
"LambdaRoleiam",
"Arn"
]
}
}
},
"LambdaRoleiam": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "saa-cache-lambda-role",
"Description": "Execution role for the cache-aside Lambda.",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
]
}
},
"RedisCacheelasticache": {
"Type": "AWS::ElastiCache::CacheCluster",
"Properties": {
"ClusterName": "saa-cache-redis",
"Engine": "redis",
"CacheNodeType": "cache.t4g.small",
"NumCacheNodes": 1,
"CacheSubnetGroupName": {
"Ref": "CacheLayerVPC10100016vpcCacheSubnetGroup"
},
"VpcSecurityGroupIds": [
{
"Fn::GetAtt": [
"CacheLayerVPC10100016vpc",
"DefaultSecurityGroup"
]
},
{
"Ref": "RedisCacheelasticacheIngressSG"
}
]
}
},
"PostgreSQLDBrds": {
"Type": "AWS::RDS::DBInstance",
"Properties": {
"DBInstanceIdentifier": "saa-cache-appdb",
"Engine": "postgres",
"DBName": "appdb",
"DBInstanceClass": "db.t4g.micro",
"DBSubnetGroupName": {
"Ref": "CacheLayerVPC10100016vpcDbSubnetGroup"
},
"VPCSecurityGroups": [
{
"Ref": "CacheLayerVPC10100016vpcdatastoresgSecurityGroup"
},
{
"Ref": "PostgreSQLDBrdsIngressSG"
}
],
"PubliclyAccessible": false,
"AllocatedStorage": "20",
"MaxAllocatedStorage": 100,
"StorageType": "gp3",
"MasterUsername": "appadmin",
"ManageMasterUserPassword": true,
"StorageEncrypted": true,
"BackupRetentionPeriod": 7
}
},
"CacheHitAlarmcloudwatch": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"AlarmName": "saa-cache-hit-rate",
"AlarmDescription": "Alert when Redis cache hit rate drops below 80%.",
"Namespace": "AWS/ElastiCache",
"MetricName": "CacheHitRate",
"Statistic": "Average",
"Period": 300,
"EvaluationPeriods": 3,
"Threshold": 80,
"ComparisonOperator": "LessThanThreshold",
"TreatMissingData": "notBreaching"
}
},
"RedisCacheelasticacheIngressSG": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Allow connected compute to ElastiCache redis on port 6379",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": 6379,
"ToPort": 6379,
"SourceSecurityGroupId": {
"Ref": "CacheLayerVPC10100016vpcappruntimesgSecurityGroup"
}
}
],
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
}
}
},
"PostgreSQLDBrdsIngressSG": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Allow connected compute to RDS postgres on port 5432",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": 5432,
"ToPort": 5432,
"SourceSecurityGroupId": {
"Ref": "CacheLayerVPC10100016vpcappruntimesgSecurityGroup"
}
}
],
"VpcId": {
"Ref": "CacheLayerVPC10100016vpc"
}
}
}
}
}Generated by TheArchitect from the diagram above. Review values such as names, CIDR ranges and instance sizes before deploying to your account.
Related templates
- Twitter/X Scale TestCloudFront behavior split, API Gateway VPC Link, public/internal ALBs, private app/data subnets, queues, media, and data stores
- Real-Time Game LeaderboardSub-millisecond leaderboard reads via ElastiCache Redis sorted sets backed by DynamoDB for durable score storage.
- ML Inference + Feature StoreServerless ML serving with a dual feature store: Redis for low-latency online features and S3 for offline training set assembly via Athena.