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

MarcoMarco
4 min read

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

0
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