Streaming Analytics
AWS architecture template · SAA-C03: Kinesis Data Stream → Lambda → S3 archive + DynamoDB + CloudWatch
Streaming Analytics is a free AWS architecture template built with CloudWatch, DynamoDB, IAM, Kinesis, Lambda and S3. 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
- CloudWatch
- DynamoDB
- IAM
- Kinesis
- Lambda
- S3
Deployment notes
Deploy-ready
- Deploys a Kinesis stream, Lambda consumer with inline code, S3 archive bucket, DynamoDB table, and iterator-lag alarm.
Generated CloudFormation — 7 resources
| Logical ID | Resource type |
|---|---|
| Kinesiskinesis | AWS::Kinesis::Stream |
| StreamConsumerlambda | AWS::Lambda::Function |
| ConsumerRoleiam | AWS::IAM::Role |
| ArchiveBuckets3 | AWS::S3::Bucket |
| EventsTabledynamodb | AWS::DynamoDB::Table |
| IteratorLagAlarmcloudwatch | AWS::CloudWatch::Alarm |
| StreamConsumerlambdaArchiveBuckets3Permission | AWS::Lambda::Permission |
View the full CloudFormation template
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Generated by TheArchitect — https://www.thecloudarchitect.dev",
"Metadata": {
"TheArchitect": {
"Edges": [
{
"From": "Kinesiskinesis",
"To": "StreamConsumerlambda",
"Label": "records"
},
{
"From": "ConsumerRoleiam",
"To": "StreamConsumerlambda",
"Label": "role"
},
{
"From": "StreamConsumerlambda",
"To": "ArchiveBuckets3",
"Label": "archive"
},
{
"From": "StreamConsumerlambda",
"To": "EventsTabledynamodb",
"Label": "write"
},
{
"From": "StreamConsumerlambda",
"To": "IteratorLagAlarmcloudwatch",
"Label": "metrics"
}
]
}
},
"Resources": {
"Kinesiskinesis": {
"Type": "AWS::Kinesis::Stream",
"Properties": {
"Name": "saa-events-stream",
"StreamModeDetails": {
"StreamMode": "PROVISIONED"
},
"ShardCount": 2,
"RetentionPeriodHours": 24
}
},
"StreamConsumerlambda": {
"Type": "AWS::Lambda::Function",
"DependsOn": [
"ConsumerRoleiam"
],
"Properties": {
"FunctionName": "saa-stream-consumer",
"Runtime": "nodejs20.x",
"Handler": "index.handler",
"MemorySize": 512,
"Architectures": [
"arm64"
],
"Timeout": 30,
"Description": "Consumes Kinesis records and fans out to S3 and DynamoDB.",
"Environment": {
"Variables": {
"APP_ENV": "demo",
"LOG_LEVEL": "info"
}
},
"TracingConfig": {
"Mode": "Active"
},
"Code": {
"ZipFile": "exports.handler = async (event) => ({ processed: Array.isArray(event.Records) ? event.Records.length : 1 });"
},
"Role": {
"Fn::GetAtt": [
"ConsumerRoleiam",
"Arn"
]
}
}
},
"ConsumerRoleiam": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "saa-stream-consumer-role",
"Description": "Execution role for the Kinesis consumer 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"
]
}
},
"ArchiveBuckets3": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "saa-stream-archive",
"VersioningConfiguration": {
"Status": "Enabled"
},
"OwnershipControls": {
"Rules": [
{
"ObjectOwnership": "BucketOwnerEnforced"
}
]
},
"BucketEncryption": {
"ServerSideEncryptionConfiguration": [
{
"ServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
},
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"BlockPublicPolicy": true,
"IgnorePublicAcls": true,
"RestrictPublicBuckets": true
},
"Tags": [
{
"Key": "Name",
"Value": "saa-stream-archive"
}
],
"NotificationConfiguration": {
"LambdaConfigurations": [
{
"Event": "s3:ObjectCreated:*",
"Function": {
"Fn::GetAtt": [
"StreamConsumerlambda",
"Arn"
]
}
}
]
}
},
"DependsOn": [
"StreamConsumerlambdaArchiveBuckets3Permission"
]
},
"EventsTabledynamodb": {
"Type": "AWS::DynamoDB::Table",
"Properties": {
"TableName": "saa-stream-events",
"BillingMode": "PAY_PER_REQUEST",
"AttributeDefinitions": [
{
"AttributeName": "streamId",
"AttributeType": "S"
},
{
"AttributeName": "ts",
"AttributeType": "N"
}
],
"KeySchema": [
{
"AttributeName": "streamId",
"KeyType": "HASH"
},
{
"AttributeName": "ts",
"KeyType": "RANGE"
}
],
"PointInTimeRecoverySpecification": {
"PointInTimeRecoveryEnabled": true
},
"SSESpecification": {
"SSEEnabled": true
}
}
},
"IteratorLagAlarmcloudwatch": {
"Type": "AWS::CloudWatch::Alarm",
"Properties": {
"AlarmName": "saa-stream-iterator-lag",
"AlarmDescription": "Alert on Kinesis iterator age above 60 seconds.",
"Namespace": "AWS/Kinesis",
"MetricName": "GetRecords.IteratorAgeMilliseconds",
"Statistic": "Maximum",
"Period": 60,
"EvaluationPeriods": 2,
"Threshold": 60000,
"ComparisonOperator": "GreaterThanOrEqualToThreshold",
"TreatMissingData": "notBreaching"
}
},
"StreamConsumerlambdaArchiveBuckets3Permission": {
"Type": "AWS::Lambda::Permission",
"DependsOn": [
"StreamConsumerlambda"
],
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Ref": "StreamConsumerlambda"
},
"Principal": "s3.amazonaws.com",
"SourceAccount": {
"Ref": "AWS::AccountId"
},
"SourceArn": {
"Fn::Sub": "arn:${AWS::Partition}:s3:::saa-stream-archive"
}
}
}
}
}Generated by TheArchitect from the diagram above. Review values such as names, CIDR ranges and instance sizes before deploying to your account.
Related templates
- IoT Fleet Telemetry PipelineKinesis stream ingests device telemetry with three parallel Lambda consumers: anomaly detection, device shadow updates, and cold-path S3 archival for Athena analytics.
- 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.
- Data PipelineS3 trigger → Lambda → DynamoDB + SQS + CloudWatch