🚀 AWS Beginner Tutorial — Build Serverless Apps with Lambda, CloudWatch, API Gateway, S3 & EventBridge Review

Whether you’re diving into serverless for the first time or just brushing up on your AWS skills, Digital Cloud Training’s AWS serverless guide walks you through a complete project using AWS Lambda, CloudWatch Logs, API Gateway, S3 static hosting, DynamoDB, and EventBridge. This is my interpretation of the guide in a more textual format for those completely new to AWS.
All source has been sourced and used from Digital Cloud Training’s GitHub repo.
✅ Part 1 — Logging to AWS CloudWatch with Python in Lambda
🛠 Step 1: Create the Lambda Function
From the AWS Console, navigate to:
Lambda > Functions > Create function
Name: WriteToCloudWatch
Runtime: Python 3.13
Architecture: x86_64
Permissions: Let AWS create a new role with basic Lambda permissions.
✅ Step 2: Confirm Creation
After clicking Create function, AWS shows a success banner.
💻 Step 3: Add Logging Code in Python
Paste this into the inline code editor:
import logging
import json
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
message = event.get('message', 'No message provided')
logger.info(message)
return {
'statusCode': 200,
'body': json.dumps('Message logged successfully!')
}
Click Deploy to apply changes.
🧪 Step 4: Create a Test Event
Use this JSON payload to simulate a message:
{
"message": "Hello, CloudWatch!"
}
Click Test and confirm successful execution in the Log output.
🔍 Step 5: Inspect Logs
Under the Monitor tab, click View CloudWatch Logs to see your message alongside Lambda execution metadata.
💡 Bonus: Invoke via AWS CLI
In CloudShell, save the payload:
{
"message": "Hello from CLI!"
}
Then run:
aws lambda invoke --function-name WriteToCloudWatch --payload fileb://payload.json response.json
Confirm in both response.json
and CloudWatch logs that the message logged successfully.
🔁 Part 2 — Triggering Lambda with S3 Uploads
🧠 Upgrade Lambda to Handle S3 Events
Update your function to log file uploads:
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
logger.info("Event: " + json.dumps(event))
for record in event['Records']:
bucket_name = record['s3']['bucket']['name']
file_key = record['s3']['object']['key']
logger.info(f"New file uploaded: {file_key} in bucket {bucket_name}")
return {
'statusCode': 200,
'body': json.dumps('S3 event processed!')
}
🔒 IAM Permissions: CloudWatch & S3
Ensure the role attached to Lambda has policies for:
logs:CreateLogGroup
, logs:CreateLogStream
, logs:PutLogEventsAmazonS3ReadOnlyAccess
🧲 Add S3 Trigger
On your target bucket (e.g., exampleBucket
), set a trigger for All object create events linked to WriteToCloudWatch
.
✅ Confirm Setup
Upload a file to the bucket. Check logs in CloudWatch for confirmation that the filename and bucket name were captured.
🌐 Part 3 — API Gateway + Lambda + DynamoDB + S3 Frontend
🔌 REST API Setup
API Gateway > Create REST API
New API name: ProductOrdersAPI
Endpoint type: Regional
Create resource path /orders
Enable CORS
Add POST method (triggers SubmitOrderFunction
)
Enable Lambda Proxy Integration
🚀 Deploy API
Deploy to a new stage prod
.
Final endpoint:
https://example-api.us-east-1.amazonaws.com/prod/orders
💻 S3 Static Website Hosting
Create bucket: myexamplebucket
Disable ACLs; allow public access
Enable static website hosting
Index document: index.html
Apply public-read bucket policy
Upload index.html
Website URL:
http://myexampleapistaticwebsite-zzzz.s3-website-us-east-1.amazonaws.com
🧪 Live Integration Test
Use the form to submit an order (e.g., iPad, Quantity: 1).
Confirm:
API Gateway logs success
DynamoDB ProductOrders
table stores entry
CloudWatch logs capture execution
🔄 Part 4 — Automate EC2 Events with EventBridge
🪧 Step 1: Define EventBridge Rule
Go to EventBridge > Create Rule
Name: stopec2
Event bus: default
Rule type: Rule with event pattern
🔍 Step 2: Event Pattern for EC2 AMI State
Service: EC2
Event type: EC2 AMI State Change
Specific state: available
Example JSON:
{
"source": ["aws.ec2"],
"detail-type": ["EC2 AMI State Change"],
"detail": {
"State": ["available"]
}
}
🎯 Step 3: Set Target to Lambda
Target: Lambda function
Function name: stopec2
Role: Let EventBridge create a new role
🔐 Step 4: Permissions
Ensure the Lambda’s execution role has AmazonEC2FullAccess
.
✅ Step 5: Complete Rule
Review and click Create Rule. Now, your Lambda triggers when an AMI becomes available.
🧪 Test & Observe Logs
Manually register an AMI or publish a test event to validate. Confirm execution via CloudWatch Logs.
🧠 Why EventBridge?
Serverless: No polling, no cron jobs
Cheap: Triggers on events only
Powerful: Works with SNS, SQS, Step Functions, more
🧾 Final Summary: End-to-End AWS Automation
You’ve now built a complete, serverless AWS app with:
Lambda: Custom logic
CloudWatch: Observability
API Gateway: Client interface
DynamoDB: Persistent data
S3: Static frontend
EventBridge: Automation workflows
Subscribe to my newsletter
Read articles from Marco directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Marco
Marco
Senior DevOps Engineer exploring the world of distributed systems