How to Build a Serverless App with AWS Lambda, S3, SNS, and EventBridge: Complete Tutorial
By Braincuber Team
Published on March 11, 2026
We watched a D2C brand burn $1,740/month on an EC2 instance running a Python script that executed once a day for 3 seconds. Three. Seconds. The rest of the time that server sat there doing nothing, racking up compute charges. AWS Lambda would have cost them $0.0000002 per invocation. This tutorial walks you through building a complete serverless application that ties together Lambda, S3, SNS, and EventBridge — the exact stack we use for automated notification systems that cost pennies instead of thousands.
What You'll Learn:
- How to create an S3 bucket and configure public access policies
- How to set up SNS topics and email/SMS subscriptions
- How to create IAM policies that give Lambda permission to publish to SNS
- How to write a Python Lambda function that fetches and publishes data
- How to schedule automatic execution with EventBridge cron rules
The Architecture: 4 AWS Services Working Together
This is not a toy demo. This is the exact pattern behind automated inventory alerts, scheduled report emails, and D2C order status notifications. Here is what each service does.
AWS Lambda (The Compute)
Runs your Python code on demand. No servers, no patching, no scaling headaches. You pay only for the milliseconds your code actually executes — typically $0.20 per million requests.
Amazon S3 (The Storage)
Stores files, images, documents — anything. 99.999999999% durability (eleven 9s). We use it here to store reference data that our Lambda function can read from.
Amazon SNS (The Messenger)
Simple Notification Service pushes messages to email, SMS, HTTP endpoints, or other AWS services. One publish call fans out to thousands of subscribers instantly.
Amazon EventBridge (The Scheduler)
Runs your Lambda on a cron schedule or in response to AWS events. This replaces the need for a dedicated server just to run a scheduled task. Think crontab, but managed and reliable.
Step by Step Guide: Build the Serverless App
Prerequisites
You need an AWS account, Python 3.x installed locally, and a code editor like VS Code. We will use the ZenQuotes API (free, no key required) to fetch random quotes that our Lambda will deliver via SNS.
Set Up Your Development Environment
Sign in to your AWS Management Console. Install Python 3.x on your machine if you do not have it. Set up the AWS CLI and configure your credentials with aws configure. Create a GitHub repo for version control.
Create an S3 Bucket for File Storage
Navigate to S3 in the AWS Console and create a new bucket with a globally unique name. Upload your reference files (documents, configs, data). Go to the Permissions tab, disable "Block public access" if you need public read, and attach a bucket policy granting s3:GetObject to make files accessible via URL.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
}
Only Make Public What Needs to Be Public
This policy grants read access to everyone on the internet. Do not use this for sensitive data, API keys, or internal documents. For production apps, restrict access using CloudFront OAI or pre-signed URLs instead.
Create an SNS Topic and Subscription
Navigate to Amazon SNS and click Create topic. Choose Standard type and give it a name (e.g., goal_topic). After creation, click the topic and go to Subscriptions tab. Click Create subscription, choose Email as protocol, enter your email address, and click Create. Check your inbox and confirm the subscription by clicking the link AWS sends you.
Create an IAM Policy for Lambda-to-SNS Access
Go to IAM, select Policies, click Create policy. Switch to the JSON tab and paste the SNS publish policy below. Replace region, account ID, and topic name with your values. Name it something like LambdaSNSPolicy. Then go to Roles, find your Lambda execution role, and attach this policy to it.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:REGION:ACCOUNT_ID:goal_topic"
}
]
}
| Placeholder | Replace With | Example |
|---|---|---|
| REGION | Your AWS region | us-east-1 |
| ACCOUNT_ID | Your 12-digit AWS account ID | 123456789012 |
| goal_topic | Your SNS topic name | order-alerts or goal_topic |
Create the Lambda Function
Navigate to AWS Lambda, click Create function, choose Author from scratch. Name it (e.g., SNSLambdaFunction), select Python 3.x as runtime, and choose "Use an existing role" selecting the role you attached the SNS policy to. Click Create function. Then add an environment variable: key = SNS_TOPIC_ARN, value = your SNS topic ARN.
import os
import json
import urllib.request
import boto3
def fetch_random_quote():
"""Fetches a random quote from the ZenQuotes API."""
api_url = "https://zenquotes.io/api/random"
try:
with urllib.request.urlopen(api_url) as response:
data = json.loads(response.read().decode())
if data and isinstance(data, list):
quote = data[0].get("q", "No quote available")
author = data[0].get("a", "Unknown author")
return f'"{quote}" - {author}'
else:
return "No quote available."
except Exception as e:
print(f"Error fetching random quote: {e}")
return "Failed to fetch quote."
def lambda_handler(event, context):
"""Lambda handler: fetch quote and publish to SNS."""
sns_topic_arn = os.getenv("SNS_TOPIC_ARN")
sns_client = boto3.client("sns")
quote = fetch_random_quote()
print(f"Fetched Quote: {quote}")
try:
sns_client.publish(
TopicArn=sns_topic_arn,
Message=quote,
Subject="Your Daily Motivational Quote",
)
print("Quote published to SNS successfully.")
except Exception as e:
print(f"Error publishing to SNS: {e}")
return {"statusCode": 500, "body": "Error publishing to SNS"}
return {"statusCode": 200, "body": "Quote sent to SNS"}
Test the Lambda Function
Click Deploy to save your code. Go to the Test tab, create a new test event with the default JSON payload, and click Test. If successful, you will see statusCode: 200 in the response and receive an email at the address you subscribed to the SNS topic. Check your spam folder if you do not see it within 30 seconds.
Create an EventBridge Schedule
Navigate to Amazon EventBridge, click Rules, then Create rule. Give it a name and choose Schedule. Select the cron scheduler to set your desired frequency (e.g., daily at 9 AM UTC: cron(0 9 * * ? *)). Set flexible time window to Off. On the Target page, choose AWS Lambda and select your function. Under permissions, choose "Use existing role." Review and create.
Every day at 9 AM UTC: cron(0 9 * * ? *)
Every hour: cron(0 * * * ? *)
Every 5 minutes: rate(5 minutes)
Weekdays at 8 AM: cron(0 8 ? * MON-FRI *)
First of every month: cron(0 0 1 * ? *)
How This Applies to D2C Operations
The quote app is a teaching example. But the architecture is identical to what we deploy for real D2C brands. Swap the ZenQuotes API for your Shopify webhook, your Odoo inventory check, or your warehouse restock threshold — and you have a production-grade alerting system for under $1/month.
Low-Stock Alerts
Lambda checks your Odoo inventory API every hour. When SKU count drops below 17 units, SNS fires an email to your purchasing team. No more manual Excel checks at 6 PM on a Friday.
Daily Revenue Reports
EventBridge triggers Lambda at 7 AM UTC. Lambda pulls yesterday's Shopify sales via API, formats a summary, and publishes the report via SNS to your founder's inbox. Cost: $0.00 per day.
Lambda Cold Starts Are Real
The first invocation after idle time takes 1-3 seconds longer (cold start). For scheduled tasks this does not matter. But if you are using Lambda behind an API Gateway for user-facing requests, consider provisioned concurrency to keep instances warm. Adds cost, but eliminates the latency spike.
Frequently Asked Questions
How much does running an AWS Lambda function cost?
The free tier gives you 1 million requests and 400,000 GB-seconds per month. After that, it is $0.20 per million requests. A daily scheduled task costs effectively nothing.
Can I use Node.js instead of Python for the Lambda function?
Yes. Lambda supports Python, Node.js, Java, Go, .NET, and Ruby. The SNS publish logic is the same via the AWS SDK, just different syntax. Choose whatever your team already knows.
Why do I need both VPC CNI and Calico for this?
You do not. This tutorial uses fully managed AWS services (Lambda, S3, SNS, EventBridge), so there is no Kubernetes or CNI involved. These services run in AWS's managed infrastructure.
Can I send SMS notifications instead of email?
Yes. When creating the SNS subscription, choose SMS as the protocol and enter a phone number. Note that SMS has per-message costs ($0.00645 per message in the US) and requires opting in to the SMS sandbox for new accounts.
How do I monitor if my Lambda function is failing silently?
Lambda automatically logs to CloudWatch. Set up a CloudWatch Alarm on the Errors metric for your function. If errors exceed 0 in a 5-minute window, trigger another SNS notification to your DevOps team.
Still Running Cron Jobs on EC2 Instances?
We have migrated D2C brands from $1,740/month EC2 schedules to Lambda pipelines that cost $0.47/month. Whether you need serverless order processing, automated Odoo inventory alerts, or Shopify webhook handlers — we architect the AWS stack so you stop paying for idle compute.
