<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ikoh Sylva</title>
    <description>The latest articles on DEV Community by Ikoh Sylva (@ikoh_sylva).</description>
    <link>https://dev.to/ikoh_sylva</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F200748%2Ff5689d79-a0bc-4166-beb5-20958f52d7dc.jpeg</url>
      <title>DEV Community: Ikoh Sylva</title>
      <link>https://dev.to/ikoh_sylva</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ikoh_sylva"/>
    <language>en</language>
    <item>
      <title>Building ChatOps with SNS and AWS Chatbot</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 08 Aug 2026 13:02:32 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/building-chatops-with-sns-and-aws-chatbot-2ibc</link>
      <guid>https://dev.to/ikoh_sylva/building-chatops-with-sns-and-aws-chatbot-2ibc</guid>
      <description>&lt;p&gt;&lt;em&gt;How to wire CloudWatch alarms through SNS and AWS Chatbot so your entire team gets real-time infrastructure alerts directly in Slack or Microsoft Teams with interactive response capabilities built in.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxw6bisma5q4um5mo3brk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxw6bisma5q4um5mo3brk.jpg" alt="Image of a credit card" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a version of cloud operations that many teams are still living in an alarm fires at 2am, the on-call engineer wakes up to 47 emails, opens three separate dashboards, and spends twenty minutes reconstructing what happened before even beginning to respond. The infrastructure was smart enough to detect the problem. The notification system failed everyone.&lt;/p&gt;

&lt;p&gt;This project puts AWS alerts where your team already lives in Slack or Microsoft Teams. When a CloudWatch alarm changes state, AWS Chatbot delivers a formatted, interactive notification directly to the channel in seconds. The team sees it together, in context, and can respond without ever leaving the conversation.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;ChatOps&lt;/strong&gt; and AWS makes it achievable with two services and about 25 minutes of configuration.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The fastest incident response starts with the right people seeing the right alert in the right place at the right time."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What Is ChatOps?
&lt;/h2&gt;

&lt;p&gt;ChatOps is a collaboration model where infrastructure operations happen inside a team's chat platform. Instead of engineers pulling data from dashboards and sharing findings in chat, the operations themselves alerts, runbooks, acknowledgements, commands originate from within the chat. The channel becomes the control plane.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Faster incident response&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;40–60% improvement with chat-based alerting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost of AWS Chatbot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0 — you only pay for underlying SNS and CloudWatch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Estimated setup time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~25 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scale&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Thousands of notifications per second&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Architecture From Alarm to Slack in Four Hops
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="err"&gt;🔔&lt;/span&gt; &lt;span class="err"&gt;CloudWatch&lt;/span&gt; &lt;span class="err"&gt;Alarm&lt;/span&gt; &lt;span class="err"&gt;(metric&lt;/span&gt; &lt;span class="err"&gt;threshold&lt;/span&gt; &lt;span class="err"&gt;breached)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;📣&lt;/span&gt;  &lt;span class="err"&gt;SNS&lt;/span&gt; &lt;span class="err"&gt;Topic&lt;/span&gt; &lt;span class="err"&gt;(publishes&lt;/span&gt; &lt;span class="err"&gt;encrypted&lt;/span&gt; &lt;span class="err"&gt;event)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;🤖&lt;/span&gt;  &lt;span class="err"&gt;AWS&lt;/span&gt; &lt;span class="err"&gt;Chatbot&lt;/span&gt; &lt;span class="err"&gt;(formats&lt;/span&gt; &lt;span class="err"&gt;message&lt;/span&gt; &lt;span class="err"&gt;into&lt;/span&gt; &lt;span class="err"&gt;rich&lt;/span&gt; &lt;span class="err"&gt;card)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;💬&lt;/span&gt;  &lt;span class="err"&gt;Slack&lt;/span&gt; &lt;span class="err"&gt;/&lt;/span&gt; &lt;span class="err"&gt;Microsoft&lt;/span&gt; &lt;span class="err"&gt;Teams&lt;/span&gt; &lt;span class="err"&gt;(team&lt;/span&gt; &lt;span class="err"&gt;notified&lt;/span&gt; &lt;span class="err"&gt;instantly)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CloudWatch monitors your infrastructure and detects threshold breaches. When an alarm changes state, it publishes a notification to an SNS topic. AWS Chatbot, subscribed to that topic, picks up the message, formats it into a rich card, and delivers it to your configured Slack channel within seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Makes AWS Chatbot More Than Just a Relay
&lt;/h2&gt;

&lt;p&gt;Before diving into setup, it's worth understanding why AWS Chatbot exists as a dedicated service rather than using a plain SNS HTTP subscription pointing at a Slack webhook. The capabilities it adds are significant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Run AWS CLI commands from Slack&lt;/strong&gt; — type &lt;code&gt;@aws describe-instances&lt;/code&gt; directly in a channel and get the response without leaving the conversation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom interactive actions&lt;/strong&gt; — buttons that trigger Lambda functions, acknowledge alerts, or launch CloudFormation stacks from a notification card&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Granular IAM guardrails&lt;/strong&gt; — define exactly which AWS operations team members can invoke from chat&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich message formatting&lt;/strong&gt; — alarm notifications rendered as structured cards, not raw JSON dumps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supports both Slack and Microsoft Teams&lt;/strong&gt; — one AWS service, two enterprise chat platforms&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;From notifications to ChatOps:&lt;/strong&gt; A basic SNS-to-Slack webhook tells you something happened. AWS Chatbot lets you respond to it without context-switching to another tool. That's the difference between being notified and being operational.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 1 — Set Up Your Environment
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Set environment variables&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws configure get region&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCOUNT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws sts get-caller-identity &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; Account &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Generate unique resource names&lt;/span&gt;
&lt;span class="nv"&gt;RANDOM_SUFFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws secretsmanager get-random-password &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--exclude-punctuation&lt;/span&gt; &lt;span class="nt"&gt;--exclude-uppercase&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--password-length&lt;/span&gt; 6 &lt;span class="nt"&gt;--require-each-included-type&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="nt"&gt;--query&lt;/span&gt; RandomPassword&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SNS_TOPIC_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"team-notifications-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RANDOM_SUFFIX&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ALARM_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"demo-cpu-alarm-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RANDOM_SUFFIX&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"✅ Environment ready for region: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2 — Create the SNS Topic With Encryption
&lt;/h2&gt;

&lt;p&gt;This SNS topic is the central hub CloudWatch publishes to it, and AWS Chatbot subscribes to it. Create it with KMS encryption enabled from the start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create SNS topic with server-side encryption&lt;/span&gt;
aws sns create-topic &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SNS_TOPIC_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--attributes&lt;/span&gt; &lt;span class="s1"&gt;'{
        "KmsMasterKeyId": "alias/aws/sns",
        "DisplayName": "Team Notifications Topic"
    }'&lt;/span&gt;

&lt;span class="c"&gt;# Store the Topic ARN&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SNS_TOPIC_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws sns get-topic-attributes &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--topic-arn&lt;/span&gt; arn:aws:sns:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCOUNT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;:&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SNS_TOPIC_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Attributes.TopicArn'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"✅ SNS topic created: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SNS_TOPIC_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;Why encrypt an SNS topic?&lt;/strong&gt; SNS messages for CloudWatch alarms can contain sensitive operational details instance IDs, IP addresses, metric values, and account identifiers. The key &lt;code&gt;alias/aws/sns&lt;/code&gt; uses the AWS-managed key for SNS, which incurs no extra cost beyond standard KMS API calls.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 3 — Connect Slack to AWS Chatbot
&lt;/h2&gt;

&lt;p&gt;AWS Chatbot's initial workspace authorisation must happen through the AWS Console there is no CLI path for this OAuth step. Navigate to &lt;strong&gt;AWS Chatbot → Configure a chat client → Slack&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Configure client&lt;/strong&gt; and you'll be redirected to Slack&lt;/li&gt;
&lt;li&gt;Select your Slack workspace from the dropdown&lt;/li&gt;
&lt;li&gt;Review the permissions AWS Chatbot requests and click &lt;strong&gt;Allow&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You'll be redirected back to the AWS console with the workspace connected&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;This step requires Slack workspace admin permissions.&lt;/strong&gt; If you're not the Slack workspace admin, you'll need to request that an admin authorise the AWS Chatbot app, or ask them to create the connection. AWS Chatbot will appear as a new app in your Slack workspace's App directory after authorisation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  For Microsoft Teams
&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;strong&gt;AWS Chatbot → Configure a chat client → Microsoft Teams&lt;/strong&gt; and follow the OAuth flow. Teams requires a Global Admin or Teams Administrator role to complete authorisation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4 — Create the Slack Channel Configuration
&lt;/h2&gt;

&lt;p&gt;With your workspace connected, configure which specific Slack channel receives AWS notifications. In the AWS Chatbot console, click &lt;strong&gt;Configure new channel&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Configuration name:&lt;/strong&gt; &lt;code&gt;team-alerts-{your-suffix}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slack channel:&lt;/strong&gt; select your target alert channel (e.g. &lt;code&gt;#aws-alerts&lt;/code&gt; or &lt;code&gt;#ops-critical&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM role:&lt;/strong&gt; create a new role (AWS Chatbot will generate one with appropriate permissions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channel guardrail policies:&lt;/strong&gt; add &lt;code&gt;ReadOnlyAccess&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SNS topics:&lt;/strong&gt; add your topic ARN from Step 2&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;What guardrail policies actually do:&lt;/strong&gt; Guardrail policies define the maximum permissions available to anyone running AWS commands from that Slack channel. If you add ReadOnlyAccess, no one can accidentally delete a resource from a Slack command regardless of their personal IAM permissions. Think of it as the outer fence IAM roles define what Chatbot can do in principle; guardrails define what's reachable from chat.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 5 — Create a CloudWatch Alarm
&lt;/h2&gt;

&lt;p&gt;For testing, we'll set a very low CPU threshold that's easy to trigger intentionally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create alarm that fires when CPU drops below 1%&lt;/span&gt;
aws cloudwatch put-metric-alarm &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--alarm-name&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ALARM_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--alarm-description&lt;/span&gt; &lt;span class="s2"&gt;"Demo CPU alarm for testing notifications"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--metric-name&lt;/span&gt; CPUUtilization &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--namespace&lt;/span&gt; AWS/EC2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--statistic&lt;/span&gt; Average &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--period&lt;/span&gt; 300 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--threshold&lt;/span&gt; 1.0 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--comparison-operator&lt;/span&gt; LessThanThreshold &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--alarm-actions&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SNS_TOPIC_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--evaluation-periods&lt;/span&gt; 1

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"✅ Alarm created: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ALARM_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"🔔 Will trigger when CPU &amp;lt; 1% (for testing)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Why CPU &amp;lt; 1% as the test threshold?&lt;/strong&gt; This creates an alarm that transitions to ALARM state almost immediately (no EC2 instances running = CPU averages zero), giving you a real state-change event to flow through SNS and Chatbot without needing actual compute resources. In production, set meaningful thresholds like &lt;code&gt;GreaterThanThreshold&lt;/code&gt; at 80% for real CPU alerts.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 6 — Test the Full Notification Pipeline
&lt;/h2&gt;

&lt;p&gt;Don't wait for an alarm publish a test message directly to the SNS topic to validate end-to-end delivery:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Send a test notification&lt;/span&gt;
aws sns publish &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--topic-arn&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SNS_TOPIC_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--subject&lt;/span&gt; &lt;span class="s2"&gt;"Test Alert: Infrastructure Notification"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--message&lt;/span&gt; &lt;span class="s1"&gt;'{
        "AlarmName": "Manual Test Alert",
        "AlarmDescription": "Testing chat notification system",
        "NewStateValue": "ALARM",
        "NewStateReason": "Testing notification delivery to Slack",
        "StateChangeTime": "'&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; +&lt;span class="s2"&gt;"%Y-%m-%dT%H:%M:%S.%3NZ"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s1"&gt;'"
    }'&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"✅ Test sent — check your Slack channel"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Validate with CLI checks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Confirm SNS topic exists and is encrypted&lt;/span&gt;
aws sns get-topic-attributes &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--topic-arn&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SNS_TOPIC_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Attributes.{Name:DisplayName,Key:KmsMasterKeyId}'&lt;/span&gt;

&lt;span class="c"&gt;# 2. Confirm alarm is pointing to SNS&lt;/span&gt;
aws cloudwatch describe-alarms &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--alarm-names&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ALARM_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'MetricAlarms[0].{Name:AlarmName,State:StateValue,Actions:AlarmActions}'&lt;/span&gt;

&lt;span class="c"&gt;# 3. Confirm AWS Chatbot is subscribed to your topic&lt;/span&gt;
aws sns list-subscriptions-by-topic &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--topic-arn&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SNS_TOPIC_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Subscriptions[*].{Protocol:Protocol,Endpoint:Endpoint}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🎉 &lt;strong&gt;Your ChatOps pipeline is live.&lt;/strong&gt; Every CloudWatch alarm state change will now appear as a formatted card in your Slack channel, visible to the whole team, in real time. No email chains, no dashboard context-switching, no missed alerts buried in an inbox.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What the Notification Looks Like in Slack
&lt;/h2&gt;

&lt;p&gt;AWS Chatbot formats CloudWatch alarm notifications into structured cards showing the alarm name, description, state transition (OK → ALARM), the reason for the state change, timestamp, and a direct link to the alarm in the AWS console. Teams get information, not data.&lt;/p&gt;

&lt;p&gt;What makes it even more powerful: team members can run AWS CLI commands directly from the channel. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@aws cloudwatch describe-alarm-history --alarm-name "prod-api-errors"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the right guardrail permissions, that command runs and the response comes back all without leaving Slack.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj0ijfsj6jv4vhvmg3q48.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj0ijfsj6jv4vhvmg3q48.jpg" alt="Image of a debit card" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting Common Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Test message sent but nothing appeared in Slack
&lt;/h3&gt;

&lt;p&gt;AWS Chatbot subscription may not be confirmed. Go to &lt;strong&gt;SNS → Subscriptions&lt;/strong&gt; and look for a subscription with protocol &lt;code&gt;AWSChatbot&lt;/code&gt;. If the status is PendingConfirmation, the channel configuration may have failed revisit the channel configuration in the AWS Chatbot console.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS Chatbot authorisation failed / workspace not connecting
&lt;/h3&gt;

&lt;p&gt;Almost always a permissions issue at the Slack level. Ensure you're authorising with a Slack workspace admin account, not a regular member.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alarm is in ALARM state but Slack received nothing
&lt;/h3&gt;

&lt;p&gt;Confirm the alarm's &lt;code&gt;AlarmActions&lt;/code&gt; includes the correct SNS topic ARN. Run &lt;code&gt;aws cloudwatch describe-alarms --alarm-names ${ALARM_NAME}&lt;/code&gt; and check the &lt;code&gt;AlarmActions&lt;/code&gt; field.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting "Access Denied" when running AWS commands from Slack
&lt;/h3&gt;

&lt;p&gt;The guardrail policy on the channel configuration is restricting the command. Either the command requires permissions beyond &lt;code&gt;ReadOnlyAccess&lt;/code&gt;, or the IAM role attached to the configuration doesn't have the specific permission needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  The ChatOps Roadmap
&lt;/h2&gt;

&lt;p&gt;The reference architecture outlines five natural extensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-environment routing&lt;/strong&gt; — separate SNS topics for dev, staging, and production, each routing to dedicated Slack channels. A prod alert in &lt;code&gt;#ops-critical&lt;/code&gt; is different from a dev alert in &lt;code&gt;#dev-alerts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom alert enrichment via Lambda&lt;/strong&gt; — subscribe a Lambda function to your SNS topic to transform raw alarm messages before delivery, adding runbook links, affected service names, and on-call rotation info&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalation workflows with Step Functions&lt;/strong&gt; — time-based escalation: if an alert in Slack goes unacknowledged for 10 minutes, Step Functions escalates from Slack to email, then SMS, then PagerDuty&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive acknowledgement buttons&lt;/strong&gt; — AWS Chatbot custom actions let engineers acknowledge alerts, trigger automated Lambda remediation, or mute an alarm from a button inside the Slack notification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-account centralisation&lt;/strong&gt; — aggregate alarms from multiple AWS accounts into a single SNS topic using cross-account role assumptions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Remove the test CloudWatch alarm&lt;/span&gt;
aws cloudwatch delete-alarms &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--alarm-names&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ALARM_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Delete the SNS topic&lt;/span&gt;
aws sns delete-topic &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--topic-arn&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SNS_TOPIC_ARN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Manual: delete channel config in AWS Chatbot console&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"🔧 https://console.aws.amazon.com/chatbot/"&lt;/span&gt;

&lt;span class="c"&gt;# Clear environment variables&lt;/span&gt;
&lt;span class="nb"&gt;unset &lt;/span&gt;SNS_TOPIC_NAME SNS_TOPIC_ARN ALARM_NAME RANDOM_SUFFIX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What I Learned From This Project
&lt;/h2&gt;

&lt;p&gt;SNS topics, CloudWatch alarms, and IAM policies were familiar territory. What was new was understanding how they compose into something with genuine operational impact.&lt;/p&gt;

&lt;p&gt;The insight that stuck most was about &lt;em&gt;where information lives&lt;/em&gt;. In a traditional ops setup, infrastructure information lives in dashboards and humans have to go get it. In a ChatOps setup, that information comes to where the humans already are. That's not just a convenience; it changes who sees the alert (the whole team, not just whoever happens to be checking email), how fast they see it (immediately, not after polling), and what they can do with it (respond directly, in context, together).&lt;/p&gt;

&lt;p&gt;A few technical things that clicked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS Chatbot is an SNS subscriber with superpowers&lt;/strong&gt; — conceptually, it's just another SNS endpoint. The magic is in what it does with the message before delivery: formatting, rich cards, IAM-backed interactivity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guardrail policies are not IAM roles&lt;/strong&gt; — they're a separate layer that caps what's possible from chat, independent of user IAM permissions. A developer with broad permissions can't accidentally use those permissions from Slack if the guardrail prevents it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KMS encryption on SNS is a one-liner&lt;/strong&gt; — adding &lt;code&gt;"KmsMasterKeyId": "alias/aws/sns"&lt;/code&gt; to the topic attributes takes ten seconds and means you're not sending operational data in cleartext. No excuse not to do this in production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test with direct SNS publish before debugging Chatbot&lt;/strong&gt; — publishing directly to the SNS topic lets you isolate whether the problem is in the alarm → SNS path or the SNS → Chatbot path&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Reference: The Full Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Services and their roles
&lt;/span&gt;
&lt;span class="err"&gt;CloudWatch&lt;/span&gt; &lt;span class="err"&gt;alarm&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;monitors&lt;/span&gt; &lt;span class="err"&gt;infrastructure&lt;/span&gt; &lt;span class="err"&gt;metrics;&lt;/span&gt; &lt;span class="err"&gt;changes&lt;/span&gt; &lt;span class="err"&gt;state&lt;/span&gt; &lt;span class="err"&gt;on&lt;/span&gt; &lt;span class="err"&gt;breach&lt;/span&gt;
&lt;span class="err"&gt;SNS&lt;/span&gt; &lt;span class="err"&gt;topic&lt;/span&gt;           &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;receives&lt;/span&gt; &lt;span class="err"&gt;alarm&lt;/span&gt; &lt;span class="err"&gt;state-change&lt;/span&gt; &lt;span class="err"&gt;events;&lt;/span&gt; &lt;span class="err"&gt;fans&lt;/span&gt; &lt;span class="err"&gt;out&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;subscribers&lt;/span&gt;
&lt;span class="err"&gt;AWS&lt;/span&gt; &lt;span class="err"&gt;Chatbot&lt;/span&gt;         &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;SNS&lt;/span&gt; &lt;span class="err"&gt;subscriber;&lt;/span&gt; &lt;span class="err"&gt;formats&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="err"&gt;delivers&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;Slack/Teams&lt;/span&gt; &lt;span class="err"&gt;channels&lt;/span&gt;
&lt;span class="err"&gt;IAM&lt;/span&gt; &lt;span class="err"&gt;role&lt;/span&gt;            &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;grants&lt;/span&gt; &lt;span class="err"&gt;Chatbot&lt;/span&gt; &lt;span class="err"&gt;permission&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;post&lt;/span&gt; &lt;span class="err"&gt;and&lt;/span&gt; &lt;span class="err"&gt;run&lt;/span&gt; &lt;span class="err"&gt;commands&lt;/span&gt;
&lt;span class="err"&gt;Guardrail&lt;/span&gt; &lt;span class="err"&gt;policy&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;caps&lt;/span&gt; &lt;span class="err"&gt;what&lt;/span&gt; &lt;span class="err"&gt;AWS&lt;/span&gt; &lt;span class="err"&gt;operations&lt;/span&gt; &lt;span class="err"&gt;are&lt;/span&gt; &lt;span class="err"&gt;accessible&lt;/span&gt; &lt;span class="err"&gt;from&lt;/span&gt; &lt;span class="err"&gt;chat&lt;/span&gt;
&lt;span class="err"&gt;KMS&lt;/span&gt; &lt;span class="err"&gt;encryption&lt;/span&gt;      &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;protects&lt;/span&gt; &lt;span class="err"&gt;message&lt;/span&gt; &lt;span class="err"&gt;content&lt;/span&gt; &lt;span class="err"&gt;at&lt;/span&gt; &lt;span class="err"&gt;rest&lt;/span&gt; &lt;span class="err"&gt;within&lt;/span&gt; &lt;span class="err"&gt;SNS&lt;/span&gt;

&lt;span class="c"&gt;# The alert chain
&lt;/span&gt;&lt;span class="err"&gt;CPU&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;80%&lt;/span&gt;
  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;CloudWatch&lt;/span&gt; &lt;span class="err"&gt;alarm&lt;/span&gt; &lt;span class="err"&gt;transitions&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;ALARM&lt;/span&gt; &lt;span class="err"&gt;state&lt;/span&gt;
      &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;Publishes&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;SNS&lt;/span&gt; &lt;span class="err"&gt;topic&lt;/span&gt; &lt;span class="err"&gt;(encrypted)&lt;/span&gt;
          &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;AWS&lt;/span&gt; &lt;span class="err"&gt;Chatbot&lt;/span&gt; &lt;span class="err"&gt;receives,&lt;/span&gt; &lt;span class="err"&gt;formats&lt;/span&gt; &lt;span class="err"&gt;message&lt;/span&gt;
              &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;Delivers&lt;/span&gt; &lt;span class="err"&gt;rich&lt;/span&gt; &lt;span class="err"&gt;card&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="c"&gt;#aws-alerts in Slack
&lt;/span&gt;               &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;Team&lt;/span&gt; &lt;span class="err"&gt;sees&lt;/span&gt; &lt;span class="err"&gt;it,&lt;/span&gt; &lt;span class="err"&gt;responds,&lt;/span&gt; &lt;span class="err"&gt;acknowledges&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="err"&gt;all&lt;/span&gt; &lt;span class="err"&gt;in&lt;/span&gt; &lt;span class="err"&gt;one&lt;/span&gt; &lt;span class="err"&gt;channel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffwt8fzoqk0pnmgidqykr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffwt8fzoqk0pnmgidqykr.jpg" alt="Image of the globe" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with &lt;strong&gt;Sanjeev Kumar’s team&lt;/strong&gt;, for the &lt;strong&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;signing up&lt;/a&gt; through the &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;link&lt;/a&gt; and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;




</description>
      <category>aws</category>
      <category>cloud</category>
      <category>chatops</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Building Real-Time File Upload Notifications with S3 and SNS</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 25 Jul 2026 08:58:54 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/building-real-time-file-upload-notifications-with-s3-and-sns-20b8</link>
      <guid>https://dev.to/ikoh_sylva/building-real-time-file-upload-notifications-with-s3-and-sns-20b8</guid>
      <description>&lt;p&gt;&lt;em&gt;How to wire Amazon S3 to Amazon SNS so that every file backed up to the cloud sends an instant email notification serverless, scalable, and set up in under 20 minutes.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;This project building a simple file backup system with S3 event notifications publishing directly to an SNS topic is one of the most practical patterns in AWS. You'll find it in compliance systems, data ingestion pipelines, media processing platforms, and anywhere that teams need instant visibility into what's landing in their cloud storage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fghnfcmsbchs0sr84jfwa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fghnfcmsbchs0sr84jfwa.jpg" alt="Image of coloful laptop" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The best backup system is the one you trust. And trust starts with knowing your backup actually ran."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  SNS vs Lambda (Choosing the Right Tool)
&lt;/h2&gt;

&lt;p&gt;Both SNS and Lambda can receive S3 events. Here's how to think about which one belongs in your architecture:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;SNS Direct&lt;/th&gt;
&lt;th&gt;Lambda Function&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Code required&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fan-out to multiple recipients&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;Manual (SES per recipient)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best when&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The notification &lt;em&gt;is&lt;/em&gt; the action&lt;/td&gt;
&lt;td&gt;The event triggers business logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Subscribers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Email, SMS, HTTP, SQS, Lambda&lt;/td&gt;
&lt;td&gt;One function (can fan out internally)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~15 minutes&lt;/td&gt;
&lt;td&gt;~30–60 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a backup notification system, SNS direct is the clear winner. We don't need to process the event we need everyone who cares to know it happened. That's pub-sub, and SNS is AWS's native pub-sub service.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture (Four Services, One Flow)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;📤 Client (uploads file) → 🪣  S3 Bucket (detects s3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;ObjectCreated event) → 📣  SNS Topic (publishes message to all subscribers) → 📬  Subscribers (email / SMS / SQS / HTTP simultaneously)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;S3 fires an event the moment an object is created. That event is published to an SNS topic, which then fans out the notification to every subscriber simultaneously. One upload, one SNS message but potentially dozens of recipients each getting it in parallel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SNS subscriber types you can attach:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email&lt;/strong&gt; — team inboxes, ops alerts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SMS&lt;/strong&gt; — on-call phone alerts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP/S&lt;/strong&gt; — webhooks, Slack, Microsoft Teams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQS Queue&lt;/strong&gt; — async downstream processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda&lt;/strong&gt; — custom logic as a downstream step&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1 — Create the S3 Bucket
&lt;/h2&gt;

&lt;p&gt;This bucket will act as your backup destination. Navigate to &lt;strong&gt;S3 → Create bucket&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name it something descriptive: &lt;code&gt;yourname-file-backups&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Choose a region — record it, all resources must be in the same region&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Bucket versioning&lt;/strong&gt;, enable it — this protects against accidental overwrites&lt;/li&gt;
&lt;li&gt;Leave &lt;strong&gt;Block all public access&lt;/strong&gt; enabled — backup buckets should never be public&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Enable versioning on backup buckets.&lt;/strong&gt; Versioning means that if a file is overwritten or deleted, the previous version is preserved. For backup use cases, this is critical without it, a bad upload can silently destroy the data you were trying to protect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Lifecycle rules for cost management (Optional)
&lt;/h3&gt;

&lt;p&gt;While not required for the notification system, lifecycle rules are worth setting up alongside it. Navigate to &lt;strong&gt;Management → Lifecycle rules → Create lifecycle rule&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transition objects to &lt;strong&gt;S3 Standard-IA&lt;/strong&gt; after 30 days (40% cheaper for infrequently accessed data)&lt;/li&gt;
&lt;li&gt;Transition to &lt;strong&gt;S3 Glacier Flexible Retrieval&lt;/strong&gt; after 90 days (up to 85% cheaper for archival)&lt;/li&gt;
&lt;li&gt;Set expiration on non-current versions after 90 days to avoid paying for old backup versions indefinitely&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;The backup cost equation:&lt;/strong&gt; S3 Standard costs $0.023/GB/month. S3 Glacier costs $0.004/GB/month. For long-lived backups, automated lifecycle transitions can reduce storage costs by 80–95% with zero manual intervention and your notification system still fires on every upload.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 2 — Create the SNS Topic
&lt;/h2&gt;

&lt;p&gt;Navigate to &lt;strong&gt;SNS → Topics → Create topic&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Type:&lt;/strong&gt; Standard (not FIFO, S3 event notifications do not support FIFO SNS topics)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; &lt;code&gt;s3-backup-notifications&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Leave all other settings as default&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create topic&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Copy the &lt;strong&gt;Topic ARN&lt;/strong&gt; from the topic details page: it looks like &lt;code&gt;arn:aws:sns:us-east-1:123456789012:s3-backup-notifications&lt;/code&gt;. You'll need it in the next two steps.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Standard topic only (FIFO is not supported).&lt;/strong&gt; S3 event notifications cannot deliver to Amazon SNS FIFO topics. If you accidentally create a FIFO topic (name ending in &lt;code&gt;.fifo&lt;/code&gt;), S3 will fail to save the notification configuration. Always use Standard topics for S3-triggered notifications.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 3 — Configure the SNS Access Policy
&lt;/h2&gt;

&lt;p&gt;This is the step most tutorials gloss over and where most people hit their first error. S3 cannot publish to your SNS topic until you explicitly grant it permission via a resource-based policy on the topic.&lt;/p&gt;

&lt;p&gt;In your SNS topic, go to &lt;strong&gt;Edit → Access policy&lt;/strong&gt;. Replace the default policy with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3-backup-sns-policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AllowS3ToPublish"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sns:Publish"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:sns:REGION:ACCOUNT_ID:s3-backup-notifications"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ArnLike"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"aws:SourceArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::yourname-file-backups"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"StringEquals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"aws:SourceAccount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR_AWS_ACCOUNT_ID"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;Anatomy of this policy:&lt;/strong&gt; The &lt;code&gt;ArnLike&lt;/code&gt; condition restricts publishing to only your specific S3 bucket preventing any other bucket (even in your own account) from sending messages to this topic. The &lt;code&gt;StringEquals&lt;/code&gt; on &lt;code&gt;aws:SourceAccount&lt;/code&gt; is a defence-in-depth measure against confused deputy attacks (a scenario where a bucket in another account tricks your topic into accepting their events.) Together: "Only my bucket, in my account, can publish here."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8bx93gjww83fidpja3e8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8bx93gjww83fidpja3e8.jpg" alt="A cool Image" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Subscribe to the SNS Topic
&lt;/h2&gt;

&lt;p&gt;In your SNS topic, click &lt;strong&gt;Create subscription&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protocol:&lt;/strong&gt; Email&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Endpoint:&lt;/strong&gt; your email address&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create subscription&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SNS immediately sends a confirmation email. &lt;strong&gt;You must click the confirmation link&lt;/strong&gt; before the subscription becomes active. Until confirmed, the subscription shows as &lt;em&gt;PendingConfirmation&lt;/em&gt; and will not receive any notifications.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Add multiple subscribers for team visibility.&lt;/strong&gt; You can add as many email subscribers as you need your entire ops team, a shared inbox, a monitoring alias. Each subscriber is independent: adding or removing one doesn't affect the others. Each subscription requires its own confirmation click.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 5 — Configure S3 Event Notifications
&lt;/h2&gt;

&lt;p&gt;Navigate to your S3 bucket → &lt;strong&gt;Properties → Event notifications → Create event notification&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Event name:&lt;/strong&gt; &lt;code&gt;BackupFileUploaded&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefix (optional):&lt;/strong&gt; e.g. &lt;code&gt;backups/&lt;/code&gt; to only trigger on files in that folder&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suffix (optional):&lt;/strong&gt; e.g. &lt;code&gt;.zip&lt;/code&gt; to only trigger on compressed archives&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event types:&lt;/strong&gt; check &lt;strong&gt;All object create events&lt;/strong&gt; (covers Put, Post, Copy, CompleteMultipartUpload)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Destination:&lt;/strong&gt; SNS topic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SNS topic:&lt;/strong&gt; select or paste the ARN of your topic&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save changes&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;If you see "Unable to validate the destination" error:&lt;/strong&gt; S3 tried to send a test message to your SNS topic and was rejected. Almost always this is the access policy from Step 3 either the bucket ARN in the &lt;code&gt;ArnLike&lt;/code&gt; condition doesn't match the actual bucket name, or the account ID is wrong.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Use prefix and suffix filters strategically.&lt;/strong&gt; If your bucket stores multiple types of content, filters save you from notification noise. A database dump (&lt;code&gt;.sql.gz&lt;/code&gt;) warrants a notification. A temporary log file being written mid-process probably doesn't.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 6 — Test the Full Pipeline
&lt;/h2&gt;

&lt;p&gt;Upload any file to your bucket via the console, CLI, or any tool that writes to S3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Upload a test backup file via CLI&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;cp&lt;/span&gt; ./my-database-backup.sql.gz &lt;span class="se"&gt;\&lt;/span&gt;
    s3://yourname-file-backups/backups/

&lt;span class="c"&gt;# Verify it's there&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;ls &lt;/span&gt;s3://yourname-file-backups/backups/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within seconds, your subscribed email should receive a notification. The raw JSON payload S3 sends through SNS looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Records"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"eventVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"eventSource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"aws:s3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"eventName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ObjectCreated:Put"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"eventTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-01-15T09:23:41.000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"s3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"bucket"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yourname-file-backups"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backups/my-database-backup.sql.gz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4096000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"eTag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"d41d8cd98f00b204e9800998ecf8427e"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🎉 &lt;strong&gt;Your backup notification system is live.&lt;/strong&gt; Every file that lands in your S3 bucket now triggers an instant notification. No Lambda to maintain, no polling to configure, no server to manage. The system scales to millions of uploads without any changes on your end.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Troubleshooting Common Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  S3 can't save the event notification "Unable to validate destination"
&lt;/h3&gt;

&lt;p&gt;The SNS topic policy isn't granting S3 permission to publish. Check that the bucket ARN in the &lt;code&gt;ArnLike&lt;/code&gt; condition exactly matches your bucket name. Note: S3 ARNs don't include a region or account ID it's just &lt;code&gt;arn:aws:s3:::bucket-name&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Confirmation email never arrived
&lt;/h3&gt;

&lt;p&gt;Check spam. SNS confirmation emails frequently land in junk folders. If it's not there after a few minutes, go to &lt;strong&gt;SNS → Subscriptions&lt;/strong&gt;, find yours in PendingConfirmation state, and click &lt;strong&gt;Request confirmation&lt;/strong&gt; to resend it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upload happens but no email received
&lt;/h3&gt;

&lt;p&gt;Confirm the subscription status in &lt;strong&gt;SNS → Subscriptions&lt;/strong&gt;. If it still shows PendingConfirmation, the confirmation link was never clicked. If Confirmed, verify the S3 event notification was saved correctly under &lt;strong&gt;S3 → Properties → Event notifications&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Receiving too many notifications / notification noise
&lt;/h3&gt;

&lt;p&gt;Add prefix or suffix filters to your S3 event notification to scope it down. Alternatively, route notifications to an SQS queue first and batch or filter there before forwarding to email.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Extensions of This Pattern
&lt;/h2&gt;

&lt;p&gt;This S3 → SNS pipeline is a foundation, not a ceiling. Once the plumbing is in place, here's how production teams extend it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-destination fan-out&lt;/strong&gt; — Add an SQS queue as a second subscriber: email goes to the ops team, the queue feeds an automated validation workflow checking file integrity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slack / Teams integration&lt;/strong&gt; — Subscribe an HTTP/S endpoint to the SNS topic, pointing at a Slack incoming webhook, for real-time channel alerts without email&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-account notifications&lt;/strong&gt; — SNS topics can notify subscribers in other AWS accounts useful for centralising backup alerts in a dedicated monitoring account in an AWS Organisations setup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance audit trails&lt;/strong&gt; — Store the SNS event messages in an SQS queue, then archive them to S3 Glacier an immutable, timestamped record that every backup ran, when it ran, and how large it was&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What I Learned From This Project
&lt;/h2&gt;

&lt;p&gt;It teaches pub-sub thinking at exactly the right level of simplicity.&lt;/p&gt;

&lt;p&gt;A few things that genuinely resonated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SNS access policies are resource-based, not identity-based&lt;/strong&gt; — just like S3 bucket policies, SNS topic policies are attached to the resource, not the caller. S3 presents as a service principal (&lt;code&gt;s3.amazonaws.com&lt;/code&gt;), and the policy must explicitly grant that principal permission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The confused deputy attack is real, not theoretical&lt;/strong&gt; — the &lt;code&gt;aws:SourceAccount&lt;/code&gt; condition exists because without it, any S3 bucket in the world could potentially publish to your SNS topic if they knew its ARN. Scoping by account prevents that. Scoping by bucket ARN tightens it further. Both conditions together that's defence in depth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fan-out changes how you think about notifications&lt;/strong&gt; — before SNS, "notify someone" meant "send them an email." After SNS, "notify" means "publish once, let the subscribers decide what to do." One upload, many outcomes, none of them coupled to each other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versioning and notifications are complementary, not redundant&lt;/strong&gt; — versioning protects the data; notifications protect the process. Together they answer two different questions: "Is the file safe?" and "Did it arrive?"&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Reference: Services and Their Roles
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Services in this project
&lt;/span&gt;
&lt;span class="nl"&gt;S3 bucket           → backup storage; fires s3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;ObjectCreated events on upload&lt;/span&gt;
&lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;versioning&lt;/span&gt;       &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;preserves&lt;/span&gt; &lt;span class="err"&gt;previous&lt;/span&gt; &lt;span class="err"&gt;file&lt;/span&gt; &lt;span class="err"&gt;versions&lt;/span&gt; &lt;span class="err"&gt;(overwrites,&lt;/span&gt; &lt;span class="err"&gt;deletions)&lt;/span&gt;
&lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;lifecycle&lt;/span&gt; &lt;span class="err"&gt;rules&lt;/span&gt;  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;auto-transitions&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;cheaper&lt;/span&gt; &lt;span class="err"&gt;storage&lt;/span&gt; &lt;span class="err"&gt;classes&lt;/span&gt; &lt;span class="err"&gt;over&lt;/span&gt; &lt;span class="err"&gt;time&lt;/span&gt;
&lt;span class="err"&gt;SNS&lt;/span&gt; &lt;span class="err"&gt;Standard&lt;/span&gt; &lt;span class="err"&gt;topic&lt;/span&gt;  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;receives&lt;/span&gt; &lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;events;&lt;/span&gt; &lt;span class="err"&gt;fans&lt;/span&gt; &lt;span class="err"&gt;out&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;all&lt;/span&gt; &lt;span class="err"&gt;active&lt;/span&gt; &lt;span class="err"&gt;subscribers&lt;/span&gt;
&lt;span class="nl"&gt;SNS access policy   → grants s3.amazonaws.com permission to sns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;Publish&lt;/span&gt;
&lt;span class="err"&gt;SNS&lt;/span&gt; &lt;span class="err"&gt;subscription&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;email&lt;/span&gt; &lt;span class="err"&gt;(or&lt;/span&gt; &lt;span class="err"&gt;SMS,&lt;/span&gt; &lt;span class="err"&gt;SQS,&lt;/span&gt; &lt;span class="err"&gt;HTTP)&lt;/span&gt; &lt;span class="err"&gt;endpoint;&lt;/span&gt; &lt;span class="err"&gt;must&lt;/span&gt; &lt;span class="err"&gt;be&lt;/span&gt; &lt;span class="err"&gt;confirmed&lt;/span&gt;

&lt;span class="c"&gt;# The event chain
&lt;/span&gt;&lt;span class="err"&gt;File&lt;/span&gt; &lt;span class="err"&gt;uploaded&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;publishes&lt;/span&gt; &lt;span class="err"&gt;JSON&lt;/span&gt; &lt;span class="err"&gt;event&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;SNS&lt;/span&gt; &lt;span class="err"&gt;topic&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;SNS&lt;/span&gt; &lt;span class="err"&gt;fans&lt;/span&gt; &lt;span class="err"&gt;out&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;all&lt;/span&gt; &lt;span class="err"&gt;confirmed&lt;/span&gt; &lt;span class="err"&gt;subscribers&lt;/span&gt; &lt;span class="err"&gt;simultaneously&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;Email&lt;/span&gt; &lt;span class="err"&gt;arrives&lt;/span&gt; &lt;span class="err"&gt;within&lt;/span&gt; &lt;span class="err"&gt;seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9o0omdeh31ix33kbrewp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9o0omdeh31ix33kbrewp.jpg" alt="Cool Image" width="799" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with &lt;strong&gt;Sanjeev Kumar’s team&lt;/strong&gt;, for the &lt;strong&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;signing up&lt;/a&gt; through the &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;link&lt;/a&gt; and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;




</description>
      <category>aws</category>
      <category>automation</category>
      <category>cloudcomputing</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Building Your First Event-Driven Pipeline with S3 and Lambda</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 13 Jun 2026 07:16:24 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/building-your-first-event-driven-pipeline-with-s3-and-lambda-2g01</link>
      <guid>https://dev.to/ikoh_sylva/building-your-first-event-driven-pipeline-with-s3-and-lambda-2g01</guid>
      <description>&lt;p&gt;&lt;em&gt;How to wire an S3 bucket to a Lambda function so that every file upload automatically triggers code without polling, without servers, and without a single cron job.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Up until this point in the series, our AWS setup has been passive. S3 holds files, CloudFront delivers them, Route 53 routes traffic. Everything waits to be asked.&lt;/p&gt;

&lt;p&gt;This project changes that. We're going to make AWS &lt;em&gt;react&lt;/em&gt;. Drop a file in an S3 bucket, and within milliseconds, a Lambda function wakes up, reads the event, and does something useful log the filename, write to CloudWatch, or fire off an email confirmation via SES.&lt;/p&gt;

&lt;p&gt;This is event-driven architecture in its simplest and most teachable form. And once you understand it at this scale, you'll recognise the same pattern everywhere in notification systems, data pipelines, media processing workflows, and audit trails.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"A server waits. An event-driven function listens. There's a difference and it matters at scale."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fab59rdpazcnw4kilm5pz.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fab59rdpazcnw4kilm5pz.JPG" alt="Image of cloudwatch logs" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What We're Building
&lt;/h2&gt;

&lt;p&gt;A file lands in S3 → S3 fires an event → Lambda receives it → Lambda acts on it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="err"&gt;📤&lt;/span&gt; &lt;span class="err"&gt;You&lt;/span&gt; &lt;span class="err"&gt;(upload&lt;/span&gt; &lt;span class="err"&gt;a&lt;/span&gt; &lt;span class="err"&gt;file)&lt;/span&gt;
    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;🪣&lt;/span&gt;  &lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;Bucket&lt;/span&gt; &lt;span class="err"&gt;(fires&lt;/span&gt; &lt;span class="err"&gt;ObjectCreated&lt;/span&gt; &lt;span class="err"&gt;event)&lt;/span&gt;
        &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;λ&lt;/span&gt;  &lt;span class="err"&gt;Lambda&lt;/span&gt; &lt;span class="err"&gt;Function&lt;/span&gt; &lt;span class="err"&gt;(wakes&lt;/span&gt; &lt;span class="err"&gt;up,&lt;/span&gt; &lt;span class="err"&gt;processes&lt;/span&gt; &lt;span class="err"&gt;event)&lt;/span&gt;
            &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;📋&lt;/span&gt;  &lt;span class="err"&gt;CloudWatch&lt;/span&gt; &lt;span class="err"&gt;Logs&lt;/span&gt; &lt;span class="err"&gt;(captures&lt;/span&gt; &lt;span class="err"&gt;output)&lt;/span&gt;
            &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;✉️&lt;/span&gt;  &lt;span class="err"&gt;SES&lt;/span&gt; &lt;span class="err"&gt;(sends&lt;/span&gt; &lt;span class="err"&gt;email&lt;/span&gt; &lt;span class="err"&gt;notification)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll implement all three response options so you understand each one:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Log to CloudWatch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Print the filename and event details to CloudWatch Logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Email via SES&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Send a confirmation email when a file arrives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Both&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Log and notify — the real-world pattern&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account with access to S3, Lambda, IAM, CloudWatch, and optionally SES&lt;/li&gt;
&lt;li&gt;Basic familiarity with the AWS console this builds directly on the S3 knowledge from our two previously posted articles and here are the links; &lt;a href="https://dev.to/ikoh_sylva/host-your-personal-website-on-aws-for-almost-free-with-s3-and-cloudfront-2km7"&gt;Link1&lt;/a&gt; and &lt;a href="https://dev.to/ikoh_sylva/your-website-your-domain-your-https-a-complete-aws-custom-domain-setup-2i2j"&gt;Link2&lt;/a&gt; ICYMI.&lt;/li&gt;
&lt;li&gt;If using the SES email option: a verified email address in SES would also be needed (covered in Step 4)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1 — Create the S3 Bucket
&lt;/h2&gt;

&lt;p&gt;If you already have an S3 bucket from our previous article, you can reuse it or create a fresh one for this exercise. Navigate to &lt;strong&gt;S3 → Create bucket&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give it a unique name, e.g. &lt;code&gt;yourname-upload-trigger-demo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Choose a region — note it down, Lambda must be in the same region&lt;/li&gt;
&lt;li&gt;Leave all other settings as default for now&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Keep bucket and Lambda in the same region:&lt;/strong&gt; S3 event notifications trigger Lambda functions within the same region. If they're in different regions, the trigger won't work. Pick a region at the start and stick to it throughout this project.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 2 — Create the Lambda Function
&lt;/h2&gt;

&lt;p&gt;Navigate to &lt;strong&gt;Lambda → Create function&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select &lt;strong&gt;Author from scratch&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Function name: &lt;code&gt;s3-upload-handler&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Runtime: &lt;strong&gt;Python 3.12&lt;/strong&gt; (or latest available)&lt;/li&gt;
&lt;li&gt;Architecture: &lt;strong&gt;x86_64&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Execution role: select &lt;strong&gt;Create a new role with basic Lambda permissions&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click &lt;strong&gt;Create function&lt;/strong&gt;. Lambda provisions your function and drops you into the inline code editor.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;What just happened with that IAM role?&lt;/strong&gt; Lambda created an execution role automatically. This role grants your function permission to write logs to CloudWatch Logs. For the SES option, you'll need to extend this role manually covered in Step 4.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The event structure Lambda receives
&lt;/h3&gt;

&lt;p&gt;Before writing code, it helps to understand what Lambda actually gets. When S3 fires an event, it sends a JSON payload that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Records"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"eventName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ObjectCreated:Put"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"s3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"bucket"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yourname-upload-trigger-demo"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reports/q4-summary.pdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;204800&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every upload becomes a record in this array. Your Lambda function digs into this structure to extract the bucket name, file key, and event type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A — Log to CloudWatch
&lt;/h3&gt;

&lt;p&gt;Paste this into the Lambda inline editor and click &lt;strong&gt;Deploy&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Records&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bucket&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;key&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;size&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ New upload detected&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;   Bucket : &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;   File   : &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;   Size   : &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; bytes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Logged successfully&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;In Lambda, every &lt;code&gt;print()&lt;/code&gt; goes to CloudWatch.&lt;/strong&gt; You don't need to import a logging library. Lambda automatically streams all stdout to CloudWatch Logs. Whatever you &lt;code&gt;print()&lt;/code&gt; shows up there within seconds.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Option B — Send an email via SES
&lt;/h3&gt;

&lt;p&gt;For this option, you'll need a verified sender address in SES first (covered in Step 4). Once that's done, use this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;ses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ses&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;SENDER&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;you@yourdomain.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;   &lt;span class="c1"&gt;# must be SES-verified
&lt;/span&gt;&lt;span class="n"&gt;RECIPIENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;you@yourdomain.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;   &lt;span class="c1"&gt;# can be same address
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Records&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bucket&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;key&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;size&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;ses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;Source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SENDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Destination&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ToAddresses&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RECIPIENT&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
            &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Subject&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New file uploaded to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Data&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File uploaded:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Bucket: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Key: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Size: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; bytes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Email sent for upload: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Email sent&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3 — Add the S3 Trigger
&lt;/h2&gt;

&lt;p&gt;Now we connect S3 to Lambda. In your Lambda function, click &lt;strong&gt;Add trigger&lt;/strong&gt; in the function overview diagram at the top of the page.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trigger source:&lt;/strong&gt; S3&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bucket:&lt;/strong&gt; select your bucket&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event types:&lt;/strong&gt; &lt;code&gt;PUT&lt;/code&gt; — this fires on every new upload&lt;/li&gt;
&lt;li&gt;Optionally add a &lt;strong&gt;Prefix&lt;/strong&gt; (e.g. &lt;code&gt;uploads/&lt;/code&gt;) or &lt;strong&gt;Suffix&lt;/strong&gt; (e.g. &lt;code&gt;.pdf&lt;/code&gt;) to filter which uploads trigger the function&lt;/li&gt;
&lt;li&gt;Acknowledge the recursive invocation warning and click &lt;strong&gt;Add&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;The recursive invocation warning — take it seriously.&lt;/strong&gt; If your Lambda function writes files back to the same S3 bucket it's triggered from, you'll create an infinite loop: upload → trigger → Lambda writes file → trigger → Lambda writes file → ... Your bill will spike before you notice. Either write to a different bucket, use a prefix/suffix filter, or simply don't write back to the same bucket from this function.&lt;/p&gt;

&lt;p&gt;🔍 &lt;strong&gt;What's happening under the hood:&lt;/strong&gt; When you add the trigger in the Lambda console, AWS does two things automatically: it adds an S3 bucket notification configuration on the bucket, and it adds a resource-based policy to your Lambda function allowing S3 to invoke it. You can inspect both. The bucket notification config lives under S3 → Properties → Event notifications, and the Lambda resource policy lives under Lambda → Configuration → Permissions.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 4 — Grant Lambda the Right Permissions
&lt;/h2&gt;

&lt;p&gt;The default Lambda execution role can write to CloudWatch Logs, which is enough for Option A. For SES email sending, you need to extend the role.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add SES send permission to the Lambda role
&lt;/h3&gt;

&lt;p&gt;Go to &lt;strong&gt;IAM → Roles&lt;/strong&gt;, find the role Lambda created (it will be named something like &lt;code&gt;s3-upload-handler-role-xxxxxxxx&lt;/code&gt;), and click &lt;strong&gt;Add permissions → Attach policies&lt;/strong&gt;. Search for and attach &lt;strong&gt;AmazonSESFullAccess&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;AmazonSESFullAccess is broad — fine for learning, not for production.&lt;/strong&gt; For a real system, create a custom IAM policy that grants only &lt;code&gt;ses:SendEmail&lt;/code&gt; on the specific identities you need. The principle of least privilege applies here just as much as it did with the S3 bucket policy in our previous article.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogp78yyiq28sxdz3ote6.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fogp78yyiq28sxdz3ote6.JPG" alt="Image of cloudwatch logs" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify your sender address in SES
&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;strong&gt;SES → Verified identities → Create identity&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select &lt;strong&gt;Email address&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter the address you'll send from&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create identity&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Check your inbox and click the verification link AWS sends&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;SES sandbox mode:&lt;/strong&gt; By default, new AWS accounts are in the SES sandbox. In sandbox mode, you can only send emails to verified addresses both the sender AND recipient must be verified. This is fine for testing. To send to anyone, you need to request production access from the SES console.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 5 — Test It End to End
&lt;/h2&gt;

&lt;p&gt;Upload any file to your S3 bucket the console, CLI, or a drag-and-drop will all work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Upload via CLI&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;cp&lt;/span&gt; ./test-document.pdf s3://yourname-upload-trigger-demo/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Check CloudWatch Logs
&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;strong&gt;CloudWatch → Log groups&lt;/strong&gt;. Look for a log group named &lt;code&gt;/aws/lambda/s3-upload-handler&lt;/code&gt;. Click the most recent log stream and you should see your print statements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="err"&gt;New&lt;/span&gt; &lt;span class="err"&gt;upload&lt;/span&gt; &lt;span class="err"&gt;detected&lt;/span&gt;
   &lt;span class="nl"&gt;Bucket &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;yourname-upload-trigger-demo&lt;/span&gt;
   &lt;span class="nl"&gt;File   &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;test-document.pdf&lt;/span&gt;
   &lt;span class="nl"&gt;Size   &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;204800 bytes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test Lambda directly (before connecting S3)
&lt;/h3&gt;

&lt;p&gt;You don't have to upload a real file to test your function. In the Lambda console, click &lt;strong&gt;Test&lt;/strong&gt; and paste a sample event to simulate what S3 sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Records"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"eventName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ObjectCreated:Put"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"s3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"bucket"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yourname-upload-trigger-demo"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test-document.pdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;204800&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you iterate on your function code quickly without uploading files every time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Troubleshooting Common Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lambda isn't firing on upload
&lt;/h3&gt;

&lt;p&gt;Check the S3 bucket notification configuration under &lt;strong&gt;S3 → Properties → Event notifications&lt;/strong&gt;. Confirm the event type is set to &lt;code&gt;PUT&lt;/code&gt; (or &lt;code&gt;All object create events&lt;/code&gt;) and the Lambda ARN is correct. Also confirm both resources are in the same region.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lambda fires but CloudWatch shows no logs
&lt;/h3&gt;

&lt;p&gt;The Lambda execution role likely doesn't have &lt;code&gt;logs:CreateLogGroup&lt;/code&gt;, &lt;code&gt;logs:CreateLogStream&lt;/code&gt;, and &lt;code&gt;logs:PutLogEvents&lt;/code&gt; permissions. The default role created by Lambda should include these, but if you created a custom role, add the &lt;code&gt;AWSLambdaBasicExecutionRole&lt;/code&gt; managed policy.&lt;/p&gt;

&lt;h3&gt;
  
  
  SES returns an error: Email address not verified
&lt;/h3&gt;

&lt;p&gt;In sandbox mode, both the sender and recipient addresses must be verified in SES. Go to &lt;strong&gt;SES → Verified identities&lt;/strong&gt; and confirm both addresses have a "Verified" status badge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function times out
&lt;/h3&gt;

&lt;p&gt;The default Lambda timeout is 3 seconds. If you're making external calls (like SES), it can occasionally be slow. Raise the timeout to 10–15 seconds under &lt;strong&gt;Lambda → Configuration → General configuration&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned From This Project
&lt;/h2&gt;

&lt;p&gt;Of all the projects in the &lt;strong&gt;Cloud Engineering Program&lt;/strong&gt;, this was the one where cloud architecture stopped feeling abstract. Watching a file upload immediately trigger code execution with no server, no polling loop, no scheduler made the event-driven model click in a way that diagrams never had.&lt;/p&gt;

&lt;p&gt;A few things that genuinely landed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Event-driven is fundamentally different from request-driven&lt;/strong&gt; — your function doesn't wait for someone to call it. The infrastructure calls it for you, the moment something happens. That changes how you design systems entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM is everywhere, and it's intentional&lt;/strong&gt; — Lambda needs permission to be invoked by S3. Lambda needs permission to send email via SES. Lambda needs permission to write logs. Every cross-service interaction requires an explicit grant. Once you internalise this, AWS architecture starts to feel less like bureaucracy and more like a coherent security model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;print()&lt;/code&gt; is enough to start&lt;/strong&gt; — CloudWatch captures everything. You don't need a logging framework, a log server, or a third-party observability tool to get started. The primitives are already there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The event payload is your contract&lt;/strong&gt; — understanding the exact structure S3 sends to Lambda, and writing code that correctly parses it, is the real skill here. The rest is just AWS console navigation.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Reference: The Full Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# Services and their roles
&lt;/span&gt;
&lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;bucket&lt;/span&gt;          &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;stores&lt;/span&gt; &lt;span class="err"&gt;files,&lt;/span&gt; &lt;span class="err"&gt;fires&lt;/span&gt; &lt;span class="err"&gt;ObjectCreated&lt;/span&gt; &lt;span class="err"&gt;events&lt;/span&gt; &lt;span class="err"&gt;on&lt;/span&gt; &lt;span class="err"&gt;upload&lt;/span&gt;
&lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;event&lt;/span&gt; &lt;span class="err"&gt;notif.&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;routes&lt;/span&gt; &lt;span class="err"&gt;PUT&lt;/span&gt; &lt;span class="err"&gt;events&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;Lambda&lt;/span&gt; &lt;span class="err"&gt;(configured&lt;/span&gt; &lt;span class="err"&gt;on&lt;/span&gt; &lt;span class="err"&gt;the&lt;/span&gt; &lt;span class="err"&gt;bucket)&lt;/span&gt;
&lt;span class="err"&gt;Lambda&lt;/span&gt; &lt;span class="err"&gt;function&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;Python&lt;/span&gt; &lt;span class="err"&gt;handler,&lt;/span&gt; &lt;span class="err"&gt;wakes&lt;/span&gt; &lt;span class="err"&gt;up&lt;/span&gt; &lt;span class="err"&gt;per&lt;/span&gt; &lt;span class="err"&gt;event,&lt;/span&gt; &lt;span class="err"&gt;processes&lt;/span&gt; &lt;span class="err"&gt;Records[]&lt;/span&gt;
&lt;span class="err"&gt;Lambda&lt;/span&gt; &lt;span class="err"&gt;exec.&lt;/span&gt; &lt;span class="err"&gt;role&lt;/span&gt;  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;IAM&lt;/span&gt; &lt;span class="err"&gt;role&lt;/span&gt; &lt;span class="err"&gt;granting&lt;/span&gt; &lt;span class="err"&gt;CloudWatch&lt;/span&gt; &lt;span class="err"&gt;Logs&lt;/span&gt; &lt;span class="err"&gt;write&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="err"&gt;SES&lt;/span&gt; &lt;span class="err"&gt;send&lt;/span&gt;
&lt;span class="err"&gt;CloudWatch&lt;/span&gt; &lt;span class="err"&gt;Logs&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;captures&lt;/span&gt; &lt;span class="err"&gt;all&lt;/span&gt; &lt;span class="err"&gt;print()&lt;/span&gt; &lt;span class="err"&gt;output&lt;/span&gt; &lt;span class="err"&gt;from&lt;/span&gt; &lt;span class="err"&gt;Lambda&lt;/span&gt; &lt;span class="err"&gt;automatically&lt;/span&gt;
&lt;span class="nl"&gt;SES                → sends transactional email (sandbox&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;verified addrs only)&lt;/span&gt;

&lt;span class="c"&gt;# The trigger chain
&lt;/span&gt;&lt;span class="err"&gt;Upload&lt;/span&gt; &lt;span class="err"&gt;file&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;S3&lt;/span&gt;  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;fires&lt;/span&gt; &lt;span class="err"&gt;event&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;Lambda&lt;/span&gt; &lt;span class="err"&gt;invoked&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;logs&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="err"&gt;email&lt;/span&gt; &lt;span class="err"&gt;sent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Now that you understand event-driven triggers, the natural next step is extending the Lambda function to do something more powerful like resizing images on upload, parsing CSV files and storing records in DynamoDB, or triggering a Step Functions workflow. The same S3 → Lambda pattern underpins all of these. Once you have the trigger working, the sky is the limit on what the function does.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivr4hwcfz95iuern1bal.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivr4hwcfz95iuern1bal.JPG" alt="Image of lamda function code" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with &lt;strong&gt;Sanjeev Kumar’s team&lt;/strong&gt;, for the &lt;strong&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;signing up&lt;/a&gt; through the &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;link&lt;/a&gt; and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;




</description>
      <category>aws</category>
      <category>cloud</category>
      <category>beginners</category>
      <category>s3</category>
    </item>
    <item>
      <title>Your Website, Your Domain, Your HTTPS — A Complete AWS Custom Domain Setup</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 06 Jun 2026 17:58:08 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/your-website-your-domain-your-https-a-complete-aws-custom-domain-setup-2i2j</link>
      <guid>https://dev.to/ikoh_sylva/your-website-your-domain-your-https-a-complete-aws-custom-domain-setup-2i2j</guid>
      <description>&lt;p&gt;&lt;em&gt;How to register a domain, wire it to Route 53, secure it with a free SSL certificate from ACM, and serve it over HTTPS through CloudFront start to finish.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;In &lt;a href="https://dev.to/ikoh_sylva/host-your-personal-website-on-aws-for-almost-free-with-s3-and-cloudfront-2km7"&gt;our last article&lt;/a&gt;, we deployed a static website to S3 and served it through CloudFront. The site was live, fast, and global but it was loading on a URL that looked like &lt;code&gt;d1abc2xyz.cloudfront.net&lt;/code&gt;. Not exactly something you'd print on a business card.&lt;/p&gt;

&lt;p&gt;This article fixes that. We're going to take that same site and give it a proper home: a custom domain, a free SSL certificate, and a verified HTTPS padlock that browsers love and employers notice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx47fw360qf0vmkipswhz.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx47fw360qf0vmkipswhz.JPG" alt="Image of AWS dashboard" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the end, your portfolio will load at &lt;code&gt;yourname.com&lt;/code&gt; over HTTPS secured, professional, and running entirely on AWS managed infrastructure.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"A CloudFront URL tells the world you know AWS. A custom HTTPS domain tells them you finished the job."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What We're Building
&lt;/h2&gt;

&lt;p&gt;This setup chains five AWS services together. Here's the full picture before we touch anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="err"&gt;🌍&lt;/span&gt; &lt;span class="err"&gt;Browser&lt;/span&gt; &lt;span class="err"&gt;(yourname.com)&lt;/span&gt;
    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;🗂️&lt;/span&gt;  &lt;span class="err"&gt;Route&lt;/span&gt; &lt;span class="err"&gt;53&lt;/span&gt; &lt;span class="err"&gt;(DNS&lt;/span&gt; &lt;span class="err"&gt;lookup)&lt;/span&gt;
        &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;🔒&lt;/span&gt;  &lt;span class="err"&gt;ACM&lt;/span&gt; &lt;span class="err"&gt;Certificate&lt;/span&gt; &lt;span class="err"&gt;(attached&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;CloudFront)&lt;/span&gt;
            &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;☁️&lt;/span&gt;  &lt;span class="err"&gt;CloudFront&lt;/span&gt; &lt;span class="err"&gt;(CDN&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="err"&gt;HTTPS&lt;/span&gt; &lt;span class="err"&gt;termination)&lt;/span&gt;
                &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;🪣&lt;/span&gt;  &lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;(private&lt;/span&gt; &lt;span class="err"&gt;origin)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Route 53 translates &lt;code&gt;yourname.com&lt;/code&gt; into CloudFront's address. CloudFront terminates the HTTPS connection using an ACM certificate, then fetches content from the private S3 bucket as needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The four phases:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;What you're doing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Phase 1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Register your domain (or bring an existing one)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Phase 2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create a hosted zone and update nameservers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Phase 3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Request a free SSL certificate via ACM with DNS validation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Phase 4&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Attach the domain and certificate to CloudFront&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Phase 1 — Register Your Domain
&lt;/h2&gt;

&lt;p&gt;You have two paths: register directly through Route 53, or bring a domain you already own from another registrar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: Register through Route 53
&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;strong&gt;Route 53 → Registered domains → Register domain&lt;/strong&gt;. Search for your name, add it to cart, and complete checkout. AWS automatically creates a hosted zone and configures the nameservers Phase 2 is essentially done for you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Pricing heads-up:&lt;/strong&gt; Route 53 domain registration starts at $13/year for .com and varies by TLD. Unlike S3 and CloudFront, domain registration has no free tier. Hosted zones also cost $0.50/month.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Option B: Bring a domain from another registrar
&lt;/h3&gt;

&lt;p&gt;If you already own a domain from Namecheap, GoDaddy, or elsewhere great. Skip this phase and go straight to Phase 2. You'll update the nameservers at your existing registrar to point at Route 53.&lt;/p&gt;




&lt;h2&gt;
  
  
  Phase 2 — Connect Your Domain to Route 53
&lt;/h2&gt;

&lt;p&gt;This is the step that hands DNS authority over to AWS. Once done, Route 53 controls where traffic for your domain goes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Create a hosted zone
&lt;/h3&gt;

&lt;p&gt;Go to &lt;strong&gt;Route 53 → Hosted zones → Create hosted zone&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enter your domain name (e.g. &lt;code&gt;yourname.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Leave type as &lt;strong&gt;Public hosted zone&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create hosted zone&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AWS generates four nameserver (NS) records automatically. They look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ns-412.awsdns-51.com
ns-1624.awsdns-11.co.uk
ns-879.awsdns-45.net
ns-1383.awsdns-44.org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy all four. You'll paste them into your registrar in the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Update nameservers at your registrar
&lt;/h3&gt;

&lt;p&gt;Log into wherever you registered your domain and find the nameserver settings. Replace the existing nameservers with the four AWS values from your hosted zone and save.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;DNS propagation takes time:&lt;/strong&gt; Nameserver changes can take anywhere from a few minutes to 48 hours to propagate globally. In practice most registrars update within 15–30 minutes. Check propagation status at &lt;code&gt;dnschecker.org&lt;/code&gt; by searching your domain for NS records.&lt;/p&gt;

&lt;p&gt;🔍 &lt;strong&gt;What's actually happening here:&lt;/strong&gt; When a browser looks up your domain, it asks the internet "who's authoritative for yourname.com?" The answer comes from your registrar's registry and it points to your nameservers. By switching those nameservers to Route 53, you're telling the entire DNS system: "Ask AWS. They know where this site lives."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Phase 3 — Request a Free SSL Certificate with ACM
&lt;/h2&gt;

&lt;p&gt;AWS Certificate Manager issues free, auto-renewing SSL/TLS certificates. Before you click anything, read this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Region matters — use us-east-1 only:&lt;/strong&gt; CloudFront only accepts ACM certificates created in the &lt;code&gt;us-east-1&lt;/code&gt; (N. Virginia) region. No exceptions. Before you start, confirm the region selector in the top-right corner of the AWS console says &lt;strong&gt;US East (N. Virginia)&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 1 — Request the certificate
&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;strong&gt;ACM → Request a certificate → Request a public certificate&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under &lt;strong&gt;Fully qualified domain names&lt;/strong&gt;, enter your root domain: &lt;code&gt;yourname.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add another name&lt;/strong&gt; and add the www version: &lt;code&gt;www.yourname.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;DNS validation&lt;/strong&gt; — faster and fully automated compared to email validation&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Request&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Always cover both root and www:&lt;/strong&gt; One certificate can cover both &lt;code&gt;yourname.com&lt;/code&gt; and &lt;code&gt;www.yourname.com&lt;/code&gt;. Do this it means visitors reach your site regardless of whether they type www or not.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 2 — Validate ownership via DNS
&lt;/h3&gt;

&lt;p&gt;ACM puts the certificate in &lt;strong&gt;Pending validation&lt;/strong&gt; state. It needs proof you own the domain before issuing the cert.&lt;/p&gt;

&lt;p&gt;Open the certificate in ACM and you'll see a validation section with CNAME records that need to be added to your DNS. Since your domain is already in Route 53, AWS makes this a single click:&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Create records in Route 53&lt;/strong&gt;. AWS adds the CNAME records automatically. Within minutes, ACM detects them and flips the certificate status to &lt;strong&gt;Issued&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;Why DNS validation works this way:&lt;/strong&gt; ACM can't issue a certificate for a domain you don't control. DNS validation proves ownership by asking you to add a specific CNAME to your DNS something only the domain owner can do. The record stays in your DNS permanently, which is how ACM silently auto-renews the certificate each year without any action from you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For reference, the CNAME ACM asks you to create looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Name:   _a79865eb4cd1a6ab990a45779b4e0b96.yourname.com
Type:   CNAME
Value:  _424c7224e9b0a0d17feb4a6acf5c0c1f.acm-validations.aws
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait until the certificate status shows &lt;strong&gt;Issued&lt;/strong&gt; before continuing. Using Route 53 for DNS, this typically takes 2–5 minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Phase 4 — Attach Everything to CloudFront
&lt;/h2&gt;

&lt;p&gt;A hosted zone, an issued certificate now let's wire it all together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Update your CloudFront distribution
&lt;/h3&gt;

&lt;p&gt;Go to &lt;strong&gt;CloudFront → Your distribution → Edit (General tab)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Under &lt;strong&gt;Alternate domain names (CNAMEs)&lt;/strong&gt;, add both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;yourname.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;www.yourname.com&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Under &lt;strong&gt;Custom SSL certificate&lt;/strong&gt;, select the certificate you just issued. It should appear in the dropdown automatically this is why the us-east-1 region requirement exists.&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Save changes&lt;/strong&gt;. CloudFront will redeploy globally give it a few minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4e00tdcrsjtuwi9comki.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4e00tdcrsjtuwi9comki.JPG" alt="Image of the website live" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Create DNS records in Route 53
&lt;/h3&gt;

&lt;p&gt;Final step: tell Route 53 to send traffic for your domain to CloudFront. Go to &lt;strong&gt;Route 53 → Hosted zones → yourname.com → Create record&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Create an &lt;strong&gt;A record&lt;/strong&gt; for the root domain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Record name:&lt;/strong&gt; leave blank (targets root domain)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record type:&lt;/strong&gt; A&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alias:&lt;/strong&gt; toggle on&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route traffic to:&lt;/strong&gt; Alias to CloudFront distribution&lt;/li&gt;
&lt;li&gt;Select your distribution from the dropdown&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repeat the same steps for &lt;code&gt;www&lt;/code&gt;: create another A alias record, enter &lt;code&gt;www&lt;/code&gt; in the record name, point it at the same CloudFront distribution.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;Why alias records instead of CNAMEs?&lt;/strong&gt; Route 53 alias records are an AWS-specific DNS extension. They work at the root domain level regular CNAMEs can't. They also update automatically when CloudFront's underlying IPs change and don't incur an extra DNS query charge.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Confirm Your Site Loads Over HTTPS
&lt;/h2&gt;

&lt;p&gt;Open a browser and visit &lt;code&gt;https://yourname.com&lt;/code&gt;. You should see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your website loading correctly&lt;/li&gt;
&lt;li&gt;A padlock icon in the address bar&lt;/li&gt;
&lt;li&gt;A valid certificate issued to your domain (click the padlock → Certificate to verify)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http://yourname.com&lt;/code&gt; automatically redirecting to HTTPS&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🎉 &lt;strong&gt;You're fully live — on your own domain, over HTTPS.&lt;/strong&gt; Your site is now globally distributed through CloudFront, secured with a certificate AWS renews automatically every year, at a URL you actually own.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Troubleshooting Common Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Certificate not appearing in the CloudFront dropdown
&lt;/h3&gt;

&lt;p&gt;Almost always a region issue. The certificate was created outside of us-east-1. Re-request it in the correct region it only takes a few minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  ERR_SSL_VERSION_OR_CIPHER_MISMATCH or certificate warning
&lt;/h3&gt;

&lt;p&gt;The alternate domain name entered in CloudFront doesn't exactly match what's on the ACM certificate. Double-check for typos they must be identical.&lt;/p&gt;

&lt;h3&gt;
  
  
  Site loads on the CloudFront URL but not the custom domain
&lt;/h3&gt;

&lt;p&gt;DNS hasn't propagated yet, or the Route 53 alias records are missing or misconfigured. Run &lt;code&gt;nslookup yourname.com&lt;/code&gt; in your terminal if it doesn't return a CloudFront address, the A records need attention.&lt;/p&gt;

&lt;h3&gt;
  
  
  www loads but the root domain doesn't (or vice versa)
&lt;/h3&gt;

&lt;p&gt;One of the two A alias records is missing. Return to Route 53 and confirm you have alias records for both the root and the www subdomain, both pointing at the same CloudFront distribution.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned From This Project
&lt;/h2&gt;

&lt;p&gt;Before doing this as part of the &lt;strong&gt;Cloud Engineering Program&lt;/strong&gt;, DNS was a black box. You typed a domain, a page appeared, and everything in between was a mystery. Wiring up Route 53, ACM, and CloudFront by hand made it concrete and a few things genuinely clicked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nameservers are delegation, not redirection&lt;/strong&gt; — you're not moving your domain, you're transferring authority over it. The internet now asks AWS, not your registrar, for answers about your domain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS validation is cryptographic proof of ownership&lt;/strong&gt; — ACM never emails you a link. The CNAME record is the proof. Only the domain owner can add it, so adding it is the trust signal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alias records solve a real DNS spec limitation&lt;/strong&gt; — CNAMEs are forbidden at the root domain level by the DNS protocol itself. Route 53 alias records are AWS's pragmatic workaround, and they're better in every measurable way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACM auto-renewal is quietly brilliant&lt;/strong&gt; — the validation CNAME never gets deleted. It sits in your DNS forever, letting ACM silently re-verify and renew your certificate each year without any action from you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this clicked from reading documentation. It clicked from doing it, watching something break, and figuring out why.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference: The Full Chain
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="c"&gt;# The complete setup, end to end
&lt;/span&gt;
&lt;span class="err"&gt;Domain&lt;/span&gt; &lt;span class="err"&gt;registrar&lt;/span&gt;  &lt;span class="err"&gt;→&lt;/span&gt;  &lt;span class="err"&gt;nameservers&lt;/span&gt; &lt;span class="err"&gt;updated&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;Route&lt;/span&gt; &lt;span class="err"&gt;53&lt;/span&gt;
&lt;span class="err"&gt;Route&lt;/span&gt; &lt;span class="err"&gt;53&lt;/span&gt;          &lt;span class="err"&gt;→&lt;/span&gt;  &lt;span class="err"&gt;hosted&lt;/span&gt; &lt;span class="err"&gt;zone&lt;/span&gt; &lt;span class="err"&gt;with&lt;/span&gt; &lt;span class="err"&gt;A&lt;/span&gt; &lt;span class="err"&gt;alias&lt;/span&gt; &lt;span class="err"&gt;records&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="err"&gt;CloudFront&lt;/span&gt;
&lt;span class="err"&gt;ACM&lt;/span&gt; &lt;span class="err"&gt;(us-east-1)&lt;/span&gt;   &lt;span class="err"&gt;→&lt;/span&gt;  &lt;span class="err"&gt;SSL&lt;/span&gt; &lt;span class="err"&gt;cert,&lt;/span&gt; &lt;span class="err"&gt;DNS-validated&lt;/span&gt; &lt;span class="err"&gt;via&lt;/span&gt; &lt;span class="err"&gt;Route&lt;/span&gt; &lt;span class="err"&gt;53&lt;/span&gt; &lt;span class="err"&gt;CNAME&lt;/span&gt;
&lt;span class="err"&gt;CloudFront&lt;/span&gt;        &lt;span class="err"&gt;→&lt;/span&gt;  &lt;span class="err"&gt;custom&lt;/span&gt; &lt;span class="err"&gt;domain&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="err"&gt;ACM&lt;/span&gt; &lt;span class="err"&gt;cert&lt;/span&gt; &lt;span class="err"&gt;attached,&lt;/span&gt; &lt;span class="err"&gt;HTTP→HTTPS&lt;/span&gt; &lt;span class="err"&gt;redirect&lt;/span&gt;
&lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;bucket&lt;/span&gt;         &lt;span class="err"&gt;→&lt;/span&gt;  &lt;span class="err"&gt;private&lt;/span&gt; &lt;span class="err"&gt;origin,&lt;/span&gt; &lt;span class="err"&gt;OAC-restricted&lt;/span&gt; &lt;span class="err"&gt;to&lt;/span&gt; &lt;span class="err"&gt;CloudFront&lt;/span&gt; &lt;span class="err"&gt;only&lt;/span&gt;

&lt;span class="c"&gt;# End result
&lt;/span&gt;&lt;span class="nl"&gt;https&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nf"&gt;//yourname.com  →  globally distributed · HTTPS · auto-renewing cert&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Now that your site lives on a custom domain over HTTPS, the next step is removing the manual deploy process entirely. Hopefully we will cover setting up a &lt;strong&gt;GitHub Actions pipeline&lt;/strong&gt; that auto-deploys on every git push and triggers a &lt;strong&gt;CloudFront cache invalidation&lt;/strong&gt; so your changes go live without you ever opening the AWS console again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0oy2r7qlyxoemk7uyoup.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0oy2r7qlyxoemk7uyoup.JPG" alt="Image of the website live" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with &lt;strong&gt;Sanjeev Kumar’s team&lt;/strong&gt;, for the &lt;strong&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;signing up&lt;/a&gt; through the &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;link&lt;/a&gt; and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>beginners</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Host Your Personal Website on AWS for (Almost) Free — With S3 and CloudFront</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 30 May 2026 08:00:19 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/host-your-personal-website-on-aws-for-almost-free-with-s3-and-cloudfront-2km7</link>
      <guid>https://dev.to/ikoh_sylva/host-your-personal-website-on-aws-for-almost-free-with-s3-and-cloudfront-2km7</guid>
      <description>&lt;p&gt;&lt;em&gt;A practical walkthrough for deploying a static portfolio, resume, or about-me page the cloud-native way with HTTPS, global delivery, and zero server maintenance.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Every cloud engineer needs a live portfolio. It proves you can ship not just talk theory. This project is deceptively simple on the surface, but underneath it teaches you S3 permissions, CDN architecture, bucket policies, and origin access control all concepts that show up on AWS certifications and real-world cloud jobs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0icdf8ayv92q65y0qjx.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0icdf8ayv92q65y0qjx.JPG" alt="Image of the AWS S3 Bucket" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this guide, I'll walk you through exactly how I deployed my own static website using &lt;strong&gt;Amazon S3&lt;/strong&gt; for storage and &lt;strong&gt;Amazon CloudFront&lt;/strong&gt; as the content delivery network no EC2, no server patching, no midnight alerts. Just clean, fast, globally distributed HTML.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The best infrastructure is the kind you don't have to babysit at 2am."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why S3 + CloudFront?
&lt;/h2&gt;

&lt;p&gt;Before we touch a single AWS console screen, let's understand the architecture we're building and why it makes sense.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;💰 &lt;strong&gt;Near-zero cost&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;S3 storage for a personal site costs pennies. CloudFront's free tier covers 1TB/month of data transfer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚡ &lt;strong&gt;Global speed&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;CloudFront caches your content at 400+ edge locations worldwide your site loads fast from Lagos to London.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔒 &lt;strong&gt;HTTPS by default&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;CloudFront provides a free SSL certificate your visitors get a padlock icon without buying anything extra.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🛠️ &lt;strong&gt;Zero servers&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;No EC2, no patching, no SSH keys. AWS manages all the infrastructure underneath.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  How the Architecture Works
&lt;/h2&gt;

&lt;p&gt;Here's the request flow from browser to your HTML file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="err"&gt;🧑‍💻&lt;/span&gt; &lt;span class="err"&gt;Visitor&lt;/span&gt;  &lt;span class="err"&gt;──HTTPS──▶&lt;/span&gt;  &lt;span class="err"&gt;☁️&lt;/span&gt; &lt;span class="err"&gt;CloudFront&lt;/span&gt; &lt;span class="err"&gt;(CDN&lt;/span&gt; &lt;span class="err"&gt;Edge)&lt;/span&gt;  &lt;span class="err"&gt;──cache&lt;/span&gt; &lt;span class="err"&gt;miss&lt;/span&gt; &lt;span class="err"&gt;only──▶&lt;/span&gt;  &lt;span class="err"&gt;🪣&lt;/span&gt; &lt;span class="err"&gt;S3&lt;/span&gt; &lt;span class="err"&gt;Bucket&lt;/span&gt; &lt;span class="err"&gt;(private&lt;/span&gt; &lt;span class="err"&gt;origin)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CloudFront sits in front of your S3 bucket as a CDN. When a visitor hits your URL, CloudFront checks if it has a cached copy at the nearest edge location. On a &lt;strong&gt;cache hit&lt;/strong&gt;, it serves instantly. On a &lt;strong&gt;miss&lt;/strong&gt;, it fetches from S3, caches it, and serves the response.&lt;/p&gt;

&lt;p&gt;Your S3 bucket can remain &lt;strong&gt;private&lt;/strong&gt; only CloudFront talks to it directly, which is far more secure than opening the bucket to the entire internet.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let's Build It Step-by-Step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 — Create Your S3 Bucket
&lt;/h3&gt;

&lt;p&gt;Log into the &lt;strong&gt;AWS Management Console&lt;/strong&gt; and navigate to &lt;strong&gt;S3 → Create bucket&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose a globally unique bucket name (e.g. &lt;code&gt;yourname-portfolio-2024&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Select your preferred AWS Region&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leave "Block all public access" checked&lt;/strong&gt; — we'll handle access through CloudFront, not by making the bucket fully public&lt;/li&gt;
&lt;li&gt;Leave versioning off for simplicity; enable it later if you want rollback support&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Common mistake:&lt;/strong&gt; Beginners often unblock all public access immediately and make the bucket fully public. This works, but it's not best practice. The cleaner and more secure approach is to keep the bucket private and let CloudFront access it via an &lt;em&gt;Origin Access Control (OAC)&lt;/em&gt; policy which is exactly what we'll do.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Step 2 — Upload Your HTML Files
&lt;/h3&gt;

&lt;p&gt;Build or gather your static website files. At minimum, you need an &lt;code&gt;index.html&lt;/code&gt;. A basic portfolio structure might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="err"&gt;my-portfolio/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="err"&gt;index.html&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="err"&gt;style.css&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="err"&gt;script.js&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="err"&gt;assets/&lt;/span&gt;
    &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="err"&gt;profile-photo.jpg&lt;/span&gt;
    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="err"&gt;resume.pdf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the S3 console, open your bucket and click &lt;strong&gt;Upload&lt;/strong&gt;. Drag your files in, keeping the folder structure intact, then click &lt;strong&gt;Upload&lt;/strong&gt; to confirm.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Pro tip:&lt;/strong&gt; If you have the AWS CLI set up, you can sync your local folder with:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 &lt;span class="nb"&gt;sync&lt;/span&gt; ./my-portfolio s3://your-bucket-name
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Much faster for future updates.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Step 3 — Enable Static Website Hosting
&lt;/h3&gt;

&lt;p&gt;In your S3 bucket, go to &lt;strong&gt;Properties → Static website hosting → Edit&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable static website hosting&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Index document&lt;/strong&gt; to &lt;code&gt;index.html&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Optionally set &lt;strong&gt;Error document&lt;/strong&gt; to &lt;code&gt;404.html&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save changes. AWS will give you an S3 website endpoint URL. Don't share this publicly it's HTTP only and bypasses CloudFront. Think of it as a staging preview.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4 — Create a CloudFront Distribution
&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;strong&gt;CloudFront → Create distribution&lt;/strong&gt;. This is where the magic happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Origin settings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Origin domain:&lt;/strong&gt; Select your S3 bucket from the dropdown (use the REST endpoint, not the website endpoint)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Origin access:&lt;/strong&gt; Choose &lt;strong&gt;Origin access control settings (recommended)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create new OAC&lt;/strong&gt; give it a name and leave signing behaviour as "Sign requests"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Default cache behaviour:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Viewer protocol policy:&lt;/strong&gt; Set to &lt;code&gt;Redirect HTTP to HTTPS&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache policy:&lt;/strong&gt; Use &lt;code&gt;CachingOptimized&lt;/code&gt; (AWS managed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Settings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Default root object:&lt;/strong&gt; Enter &lt;code&gt;index.html&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price class:&lt;/strong&gt; &lt;code&gt;Use all edge locations&lt;/code&gt; for best global performance, or restrict to a region to reduce cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click &lt;strong&gt;Create distribution&lt;/strong&gt;. CloudFront will take a few minutes to deploy globally the status changes from "Deploying" to a green "Enabled".&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 5 — Add the Bucket Policy for CloudFront OAC
&lt;/h3&gt;

&lt;p&gt;After creating the distribution, the console will show a banner prompting you to update your S3 bucket policy. Click &lt;strong&gt;Copy policy&lt;/strong&gt;, then navigate back to your S3 bucket → &lt;strong&gt;Permissions → Bucket policy → Edit&lt;/strong&gt; and paste it in.&lt;/p&gt;

&lt;p&gt;The generated policy looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AllowCloudFrontServicePrincipal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cloudfront.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::your-bucket-name/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"StringEquals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"AWS:SourceArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:cloudfront::ACCOUNT_ID:distribution/DIST_ID"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🔍 &lt;strong&gt;What this policy does:&lt;/strong&gt; It grants the CloudFront service principal read access (&lt;code&gt;s3:GetObject&lt;/code&gt;) to every object in your bucket but &lt;em&gt;only&lt;/em&gt; from your specific CloudFront distribution. Not from anyone else's CloudFront. Not from the public internet. Just yours.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvn0yy7kzs28jsxp77yx.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvn0yy7kzs28jsxp77yx.JPG" alt="Image of the webpage" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6 — Test Your Live Site
&lt;/h3&gt;

&lt;p&gt;Go back to CloudFront and copy your &lt;strong&gt;Distribution domain name&lt;/strong&gt; it looks like &lt;code&gt;d1abc2defgh3ij.cloudfront.net&lt;/code&gt;. Paste it in your browser.&lt;/p&gt;

&lt;p&gt;You should see your &lt;code&gt;index.html&lt;/code&gt; rendered, served over HTTPS, with a valid SSL certificate for free.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🎉 &lt;strong&gt;You're live!&lt;/strong&gt; Your personal website is now globally distributed across AWS's edge network. Whether someone visits from Lagos, London, or Los Angeles they're getting a fast, secure experience.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Optional But Recommended: Use Your Own Domain
&lt;/h2&gt;

&lt;p&gt;The CloudFront URL works fine, but &lt;code&gt;yourname.com&lt;/code&gt; looks far more professional. Here's the short version:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Register a domain via &lt;strong&gt;Route 53&lt;/strong&gt; (or bring your own from Namecheap, GoDaddy, etc.)&lt;/li&gt;
&lt;li&gt;Request a free SSL certificate via &lt;strong&gt;AWS Certificate Manager (ACM)&lt;/strong&gt; in the &lt;strong&gt;us-east-1&lt;/strong&gt; region (required for CloudFront)&lt;/li&gt;
&lt;li&gt;Add your custom domain as an &lt;strong&gt;Alternate domain name (CNAME)&lt;/strong&gt; in your CloudFront distribution settings and attach the ACM certificate&lt;/li&gt;
&lt;li&gt;In Route 53, create an &lt;strong&gt;A record (alias)&lt;/strong&gt; pointing to your CloudFront distribution&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What I Learned From This Project
&lt;/h2&gt;

&lt;p&gt;When I first completed this as part of the &lt;strong&gt;Cloud Engineering Program&lt;/strong&gt;, I thought it was going to be a simple file-upload exercise. It turned out to be a surprisingly rich lesson in cloud fundamentals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IAM and resource-based policies&lt;/strong&gt; — the bucket policy taught me how AWS evaluates permissions at the resource level, not just the user level&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The principle of least privilege&lt;/strong&gt; — keeping the S3 bucket private and exposing it only through CloudFront OAC is a real-world security pattern, not just textbook advice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CDN architecture&lt;/strong&gt; — understanding cache hits vs. misses, TTLs, and edge locations made CloudFront feel less magical and more engineerable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS and SSL&lt;/strong&gt; — hooking up Route 53 and ACM demystified how HTTPS actually works end-to-end&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't just resume bullet points. They're the building blocks of almost every AWS architecture you'll work on professionally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference: Services Used
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Role in This Project&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Amazon S3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Object storage for your HTML/CSS/JS/assets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;S3 Static Hosting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Turns the bucket into a web server (origin)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bucket Policy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JSON policy granting CloudFront read access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CloudFront&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CDN that caches and delivers content globally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OAC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Origin Access Control secure S3↔CloudFront connection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ACM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free SSL/TLS certificate &lt;em&gt;(optional, custom domain)&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Route 53&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DNS routing &lt;em&gt;(optional, custom domain)&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Once your static site is live, try extending it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add a &lt;strong&gt;CI/CD pipeline with GitHub Actions&lt;/strong&gt; to auto-deploy on every push to your repo&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;CloudFront invalidations&lt;/strong&gt; (&lt;code&gt;aws cloudfront create-invalidation&lt;/code&gt;) to clear the cache when you update your content&lt;/li&gt;
&lt;li&gt;Explore &lt;strong&gt;S3 access logging&lt;/strong&gt; to see who's visiting your site&lt;/li&gt;
&lt;li&gt;Deploy a &lt;strong&gt;React or Next.js build&lt;/strong&gt; the same S3 + CloudFront pattern scales directly to frontend frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The static web hosting pattern is one of the most reusable skills in your AWS toolkit. Once you have it down, you'll reach for it constantly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0avzmx9z1sucfo1uzkhi.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0avzmx9z1sucfo1uzkhi.JPG" alt="Image of the webpage" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with &lt;strong&gt;Sanjeev Kumar’s team&lt;/strong&gt;, for the &lt;strong&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;signing up&lt;/a&gt; through the &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;link&lt;/a&gt; and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;




</description>
      <category>aws</category>
      <category>cloud</category>
      <category>beginners</category>
      <category>cloudskills</category>
    </item>
    <item>
      <title>Monitoring Containers on AWS ECS with CloudWatch</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 23 May 2026 19:46:39 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/monitoring-containers-on-aws-ecs-with-cloudwatch-55d4</link>
      <guid>https://dev.to/ikoh_sylva/monitoring-containers-on-aws-ecs-with-cloudwatch-55d4</guid>
      <description>&lt;p&gt;One of the biggest realizations I had during my cloud engineering journey was this:&lt;/p&gt;

&lt;p&gt;Deploying an application is only half the job.&lt;/p&gt;

&lt;p&gt;The other half?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Monitoring it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Understanding how it behaves under load.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Knowing when something is wrong before users complain.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because in real-world cloud environments, applications are constantly consuming resources, handling requests, and responding to changing traffic patterns. If you’re not monitoring them properly, you’re essentially operating blind.&lt;/p&gt;

&lt;p&gt;That’s exactly what this hands-on project aims to help us understand.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through how I monitored containerized workloads running on Amazon ECS, configured task resource settings, and visualized metrics using Amazon CloudWatch dashboards.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foinvrknj7dw6ner6xyx5.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foinvrknj7dw6ner6xyx5.JPG" alt="Image of AWS ECS dashboard" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What we’ll Be Building
&lt;/h2&gt;

&lt;p&gt;In this project, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deploy a containerized application on ECS &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure CPU and memory allocation in the task definition &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monitor resource usage using CloudWatch &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build a dashboard with CPU and memory widgets &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simulate load to observe metric changes in real time&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, you’ll understand how to move from simply running containers to actually observing and managing them effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Monitoring Matters
&lt;/h2&gt;

&lt;p&gt;Imagine deploying an application that suddenly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Runs out of memory &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uses excessive CPU &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Becomes slow under traffic spikes &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without monitoring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You won’t know why performance dropped&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Troubleshooting becomes difficult&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Downtime becomes more likely&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With monitoring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You gain visibility&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can detect issues early&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You make informed scaling decisions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why observability is such a huge part of modern DevOps and Cloud Engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Users
   |
   v
Amazon ECS Cluster
   |
Running ECS Service
   |
Task Definition
(CPU + Memory Allocation)
   |
CloudWatch Metrics &amp;amp; Dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1: ECS Cluster and Running Service
&lt;/h2&gt;

&lt;p&gt;The first step was deploying a containerized application on ECS.&lt;/p&gt;

&lt;p&gt;The deployment included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An ECS Cluster &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Running ECS Service &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Active ECS Tasks &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the foundation where your application runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Configure Task Definition Resources
&lt;/h2&gt;

&lt;p&gt;One thing beginners often overlook is this:&lt;br&gt;
Containers don’t have unlimited resources.&lt;/p&gt;

&lt;p&gt;When creating the ECS task definition, I configured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CPU allocation &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memory allocation &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CPU: 512 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memory: 1024 MiB &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Resource allocation helps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Prevent resource exhaustion &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improve application stability &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optimize cloud costs &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define scaling expectations &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how cloud platforms control workload behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Monitoring with CloudWatch
&lt;/h2&gt;

&lt;p&gt;Now comes the exciting part.&lt;/p&gt;

&lt;p&gt;Once the ECS service was running, AWS automatically started sending metrics to CloudWatch.&lt;/p&gt;

&lt;p&gt;I created a dashboard showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CPU utilization &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memory utilization &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These widgets provided real-time visibility into how the container was behaving.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8zunwoj64yvowifkivl.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8zunwoj64yvowifkivl.JPG" alt="Image of AWS analytics dashboard" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Dashboard
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to CloudWatch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Navigate to Dashboards &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Dashboard &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add Widgets: &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ECS CPU Utilization &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ECS Memory Utilization &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What These Metrics Tell You
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CPU Utilization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Shows how much processing power the container is using.&lt;/p&gt;

&lt;p&gt;High CPU may indicate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Heavy traffic &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inefficient code &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Need for scaling &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Memory Utilization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Shows RAM consumption.&lt;/p&gt;

&lt;p&gt;High memory usage may indicate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Memory leaks &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Insufficient allocation &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Application instability risks &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Simulate Load
&lt;/h2&gt;

&lt;p&gt;This was one of the most interesting parts.&lt;/p&gt;

&lt;p&gt;To see real metric changes, I simulated load against the application using repeated browser refreshes or lightweight testing tools.&lt;/p&gt;

&lt;p&gt;And suddenly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CPU usage increased&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memory usage shifted&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Watching the graphs move in real time made everything feel much more practical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Simulating Load Is Important
&lt;/h2&gt;

&lt;p&gt;This helps you understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How applications behave under pressure &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When scaling might be needed &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How monitoring tools detect changes &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Mistakes Beginners Make
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Ignoring Resource Limits&lt;br&gt;
Containers can crash if memory is exhausted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not Monitoring Applications&lt;br&gt;
You can’t fix what you can’t see.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Misinterpreting Metrics&lt;br&gt;
Temporary spikes are normal patterns matter more.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What This Project Really Teaches
&lt;/h2&gt;

&lt;p&gt;At first glance, this might seem like:&lt;/p&gt;

&lt;p&gt;“Just another ECS deployment.”&lt;/p&gt;

&lt;p&gt;But it’s actually teaching something deeper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Operational visibility &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resource management &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Observability fundamentals &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance awareness &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the most important transitions in cloud engineering is moving from:&lt;/p&gt;

&lt;p&gt;“My application is running” to “I understand how my application is performing.”&lt;/p&gt;

&lt;p&gt;That’s where monitoring changes everything.&lt;/p&gt;

&lt;p&gt;This project helped reinforce that cloud engineering isn’t only about infrastructure it’s also about visibility, reliability, and operational intelligence.&lt;/p&gt;

&lt;p&gt;And honestly? That’s where things start getting really interesting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdz55wutdur07anuygrh.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdz55wutdur07anuygrh.JPG" alt="Image of Nginx home page" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with Sanjeev Kumar’s team, for the DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;Apply &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;signing up&lt;/a&gt; through the &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;link&lt;/a&gt; and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>ecs</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Deploying Metabase on AWS ECS (Fargate) with PostgreSQL (RDS)</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 16 May 2026 07:42:54 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/deploying-metabase-on-aws-ecs-fargate-with-postgresql-rds-41pa</link>
      <guid>https://dev.to/ikoh_sylva/deploying-metabase-on-aws-ecs-fargate-with-postgresql-rds-41pa</guid>
      <description>&lt;p&gt;At some point in your cloud journey, you stop just deploying applications and start thinking about data, persistence, and real-world architecture.&lt;/p&gt;

&lt;p&gt;Because most production applications don’t just run they store, query, and visualize data.&lt;/p&gt;

&lt;p&gt;That’s exactly what this project is about.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmxh5hhqdaarr2vvj1c5.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmxh5hhqdaarr2vvj1c5.JPG" alt="Image of the AWS ECS Cluster" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through how I deployed Metabase (an open-source business intelligence tool) on AWS using ECS with Fargate, and connected it to a PostgreSQL database hosted on RDS.&lt;/p&gt;

&lt;p&gt;This is no longer just a “hello world” setup this is a real application backed by a real database.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We’ll Be Building
&lt;/h2&gt;

&lt;p&gt;In this project, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deploy Metabase using containers &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run it on Amazon ECS (Fargate) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a PostgreSQL database using Amazon RDS &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connect the application to the database &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure networking and security for communication &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, we’ll have a fully functional data application in the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This project introduces critical real-world concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Application + Database architecture &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Containerized workloads &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Managed databases (RDS) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secure service-to-service communication &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Environment variable configuration &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the kind of setup you’ll see in production systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User (Browser)
     |
     v
ECS Service (Fargate)
     |
Metabase Container
     |
     v
Amazon RDS (PostgreSQL)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both ECS and RDS must be in the same VPC for private communication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create the RDS PostgreSQL Database
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to RDS → Create Database &lt;/li&gt;
&lt;li&gt;Choose: &lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Engine: PostgreSQL &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Template: Free tier (if available)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;DB instance identifier: &lt;code&gt;metabase-db&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Username: &lt;code&gt;postgres&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Password: (your choice) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Networking Settings&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Place RDS in your VPC &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose a private subnet (recommended) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disable public access (best practice) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security Group for RDS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add inbound rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Port: 5432 (PostgreSQL) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Source: ECS security group &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows only your container to access the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Create ECS Cluster (Fargate)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to ECS &lt;/li&gt;
&lt;li&gt;Create a cluster &lt;/li&gt;
&lt;li&gt;Choose Fargate (Networking only) &lt;/li&gt;
&lt;li&gt;Name it: metabase-cluster&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 3: Create Task Definition
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to Task Definitions → Create &lt;/li&gt;
&lt;li&gt;Choose Fargate &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Container Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Container name: &lt;code&gt;metabase&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Image: &lt;code&gt;metabase/metabase&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Port mapping: &lt;br&gt;
Container port: 3000 &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Environment Variables&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;MB_DB_TYPE&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;span class="py"&gt;MB_DB_DBNAME&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;metabase&lt;/span&gt;
&lt;span class="py"&gt;MB_DB_PORT&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5432&lt;/span&gt;
&lt;span class="py"&gt;MB_DB_USER&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;span class="py"&gt;MB_DB_PASS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yourpassword&lt;/span&gt;
&lt;span class="py"&gt;MB_DB_HOST&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;RDS-ENDPOINT&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;RDS-ENDPOINT&amp;gt;&lt;/code&gt; with your database endpoint.&lt;/p&gt;

&lt;p&gt;This is how Metabase connects to PostgreSQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Create ECS Service
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Launch type: Fargate &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Task definition: metabase-task &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Number of tasks: 1 &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fje6wlrlwsuz9460drfja.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fje6wlrlwsuz9460drfja.JPG" alt="Image of Metabase Database" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Networking Setup&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use the same VPC as RDS &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select subnets (public or private depending on access strategy) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable public IP (if accessing via browser) &lt;br&gt;
Security Group for ECS&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Add inbound rule:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Port: 3000 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Source: your IP (recommended) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: Deploy and Run
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Start the service &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wait for task status → RUNNING &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 6: Access Metabase
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Get the public IP of the ECS task &lt;/li&gt;
&lt;li&gt;Open: 
&lt;code&gt;http://&amp;lt;public-ip&amp;gt;:3000&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should see the Metabase setup screen!&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;ECS and RDS in different VPCs&lt;br&gt;
They won’t communicate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Incorrect RDS endpoint&lt;br&gt;
Connection will fail.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Missing security group rule (5432)&lt;br&gt;
Database access will be blocked.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wrong environment variables&lt;br&gt;
Metabase won’t initialize properly.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What This Project Teaches You
&lt;/h2&gt;

&lt;p&gt;This project is a major step forward.&lt;/p&gt;

&lt;p&gt;You learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How applications connect to databases &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to configure secure communication &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to run stateful applications in the cloud &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How real-world systems are structured&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is no longer just infrastructure it’s application architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;p&gt;This setup is similar to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Internal analytics dashboards &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Business intelligence platforms &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SaaS reporting tools &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monitoring and metrics visualization &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deploying Metabase with ECS and RDS is where things start to feel real.&lt;/p&gt;

&lt;p&gt;You’re no longer just launching resources you’re building connected systems.&lt;/p&gt;

&lt;p&gt;And that’s the difference between:&lt;/p&gt;

&lt;p&gt;“Learning cloud” and “Thinking like a cloud engineer”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjxo7ee3ra8rn8noobke.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjxo7ee3ra8rn8noobke.JPG" alt="Image of a Metabase Site" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with &lt;strong&gt;Sanjeev Kumar’s team&lt;/strong&gt;, for the DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;signing up&lt;/a&gt; through the &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;link&lt;/a&gt; and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>cloudcomputing</category>
      <category>awsecsfargate</category>
    </item>
    <item>
      <title>Running Grafana on AWS ECS (Fargate)</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 09 May 2026 19:48:31 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/running-grafana-on-aws-ecs-fargate-p9g</link>
      <guid>https://dev.to/ikoh_sylva/running-grafana-on-aws-ecs-fargate-p9g</guid>
      <description>&lt;p&gt;At some point in your cloud journey, you move beyond just deploying servers…&lt;/p&gt;

&lt;p&gt;…and start thinking about observability.&lt;/p&gt;

&lt;p&gt;Because building systems is one thing.&lt;/p&gt;

&lt;p&gt;Understanding how they behave in real time is another.&lt;/p&gt;

&lt;p&gt;That’s where tools like Grafana come in.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through how I deployed Grafana on AWS using ECS with Fargate a fully managed container service without managing any servers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8i5gvnmf91p5ptypknol.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8i5gvnmf91p5ptypknol.JPG" alt="Image of the grafana ECS service on AWS" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What We’ll Be Building
&lt;/h2&gt;

&lt;p&gt;In this project, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deploy Grafana using containers &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Amazon ECS with Fargate (serverless compute for containers) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expose the application on port 3000 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure networking and security &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access Grafana via our browser &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, we’ll have a live Grafana dashboard running in the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This project introduces you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Containerized applications &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Serverless container orchestration &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Networking in ECS &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security group configuration &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Observability tools (Grafana)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are real-world DevOps and Cloud Engineering skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Internet
   |
Public Subnet
   |
ECS Service (Fargate)
   |
Grafana Container (Port 3000)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No EC2 instances needed Fargate handles everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create an ECS Cluster
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to ECS in the AWS Console &lt;/li&gt;
&lt;li&gt;Click Create Cluster &lt;/li&gt;
&lt;li&gt;Choose Fargate (Networking only) &lt;/li&gt;
&lt;li&gt;Give it a name (e.g., grafana-cluster) &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 2: Create a Task Definition
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to Task Definitions → Create &lt;/li&gt;
&lt;li&gt;Select Fargate &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Task name: &lt;code&gt;grafana-task&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CPU: 0.5 vCPU &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memory: 1GB &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Add Container&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Container name: grafana &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Image: &lt;code&gt;grafana/grafana&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Port mapping: &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Container port: 3000&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tells ECS to expose Grafana’s default port.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Create a Service
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to your cluster &lt;/li&gt;
&lt;li&gt;Click Create Service &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Configure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Launch type: Fargate &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Task definition: &lt;code&gt;grafana-task&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Number of tasks: 1 &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Networking Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This step is critical.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Choose a VPC &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select a public subnet &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable Auto-assign public IP &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Configure Security Group
&lt;/h2&gt;

&lt;p&gt;Create or modify a security group:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inbound Rule&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Type: Custom TCP &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Port: 3000 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Source: 0.0.0.0/0 (or restrict to your IP for better security) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows access to Grafana via browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27bkowgyx5sqlwrm4oy5.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27bkowgyx5sqlwrm4oy5.JPG" alt="Image of grafana login page" width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Deploy and Run
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Launch the service &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wait for the task to reach RUNNING state &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 6: Access Grafana
&lt;/h2&gt;

&lt;p&gt;Once running:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to ECS → Tasks &lt;/li&gt;
&lt;li&gt;Copy the Public IP &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Open in browser:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://&amp;lt;public-ip&amp;gt;:3000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should see the Grafana login page!&lt;/p&gt;

&lt;h2&gt;
  
  
  Default Login
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Username: admin &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Password: admin &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(You’ll be prompted to change it immediately.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Assignment Deliverable (Proof)
&lt;/h2&gt;

&lt;p&gt;To confirm your setup, capture screenshots showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ECS cluster &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Running task &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Task public IP &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Grafana UI in browser &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This proves:&lt;/p&gt;

&lt;p&gt;✔ Successful deployment&lt;br&gt;
✔ Proper networking&lt;br&gt;
✔ Working containerized application&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Forgetting to open port 3000&lt;br&gt;
You won’t be able to access Grafana.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not assigning a public IP&lt;br&gt;
Your service won’t be reachable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using wrong port mapping&lt;br&gt;
Grafana won’t load properly.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What This Project Teaches You
&lt;/h2&gt;

&lt;p&gt;This isn’t just about Grafana.&lt;/p&gt;

&lt;p&gt;It teaches you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How containers are deployed in the cloud &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How ECS and Fargate work &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to expose applications securely &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How modern infrastructure avoids managing servers &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is exactly how modern DevOps teams deploy applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;p&gt;Grafana is widely used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Monitoring cloud infrastructure &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Visualizing metrics (CPU, memory, logs) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrating with tools like Prometheus and CloudWatch &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deploying Grafana on ECS Fargate is a powerful step forward in your cloud journey.&lt;/p&gt;

&lt;p&gt;It moves you from:&lt;/p&gt;

&lt;p&gt;“I can launch servers” to “I can now deploy and run real applications in the cloud”&lt;/p&gt;

&lt;p&gt;And that’s where things start to get exciting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3254c94if4ysfhalm47v.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3254c94if4ysfhalm47v.JPG" alt="Image of grafana home page" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with Sanjeev Kumar’s team, for the DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By signing up through the &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;link&lt;/a&gt; and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>cloudcomputing</category>
      <category>aws</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Building a Multi-VPC Architecture on AWS</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 02 May 2026 07:37:14 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/building-a-multi-vpc-architecture-on-aws-30m3</link>
      <guid>https://dev.to/ikoh_sylva/building-a-multi-vpc-architecture-on-aws-30m3</guid>
      <description>&lt;p&gt;When people begin learning cloud networking, they often start with a single VPC.&lt;br&gt;
And that’s fine… until you realize that real-world cloud environments rarely stop at just one VPC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0a5cjwccqyiwcfgntlq3.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0a5cjwccqyiwcfgntlq3.JPG" alt="Image of the AWS management console" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Organizations separate workloads for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Security &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scalability &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Team isolation &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Environment segmentation (Dev, Staging, Production) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At that point, a new question arises:&lt;/p&gt;

&lt;p&gt;How do these isolated networks communicate with each other securely?&lt;/p&gt;

&lt;p&gt;That’s exactly what this hands-on project explores.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We’ll Be Building
&lt;/h2&gt;

&lt;p&gt;In this guide, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create two separate VPCs &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Design public and private subnets in each VPC &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Establish a VPC Peering connection &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure route tables to enable communication &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, we’ll have a basic multi-VPC architecture, similar to what is used in real production environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This project introduces core networking concepts every cloud engineer must understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Network isolation &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CIDR block design &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Routing between networks &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Private communication without the internet &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are foundational skills for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cloud Engineers &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DevOps Engineers &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Solutions Architects &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VPC-A (10.10.0.0/16)          VPC-B (10.20.0.0/16)
----------------------        ----------------------
Public Subnet                Public Subnet
Private Subnet               Private Subnet
        |                          |
        -------- VPC Peering -------
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No Internet Gateway or NAT Gateway required this is purely internal communication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create VPC-A
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Name: VPC-A &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CIDR block: 10.10.0.0/16 &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: Create Subnets in VPC-A
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Public Subnet: 10.10.1.0/24 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Private Subnet: 10.10.2.0/24 &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Create VPC-B
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Name: VPC-B &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CIDR block: 10.20.0.0/16 &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Create Subnets in VPC-B
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Public Subnet: 10.20.1.0/24 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Private Subnet: 10.20.2.0/24 &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: Create VPC Peering Connection
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to VPC Dashboard → Peering Connections &lt;/li&gt;
&lt;li&gt;Click Create Peering Connection &lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select: &lt;br&gt;
Requester: VPC-A &lt;br&gt;
Accepter: VPC-B &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create and accept the request &lt;br&gt;
Once accepted, the VPCs are logically connected but not yet able to communicate.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmubb1p37dm9ojo7o0br.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmubb1p37dm9ojo7o0br.JPG" alt="Image of the AWS VPC management console " width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Update Route Tables (Critical Step)
&lt;/h2&gt;

&lt;p&gt;This is where many beginners get stuck.&lt;/p&gt;

&lt;p&gt;For VPC-A Route Table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Destination: 10.20.0.0/16 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Target: VPC Peering Connection &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For VPC-B Route Table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Destination: 10.10.0.0/16 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Target: VPC Peering Connection &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without this step, traffic will not flow, even though peering exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Traffic from VPC-A → VPC-B is routed through the peering connection &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Traffic from VPC-B → VPC-A follows the reverse route &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This enables private, secure communication between networks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the Setup
&lt;/h2&gt;

&lt;p&gt;To validate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Launch EC2 instances in each VPC &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use private IPs to ping between them &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If configured correctly:&lt;/p&gt;

&lt;p&gt;✔ Instances should communicate successfully&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Limitations of VPC Peering
&lt;/h2&gt;

&lt;p&gt;Understanding limitations is key:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No transitive routing (A → B → C won’t work automatically) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CIDR blocks must not overlap &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each route must be manually configured &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What This Project Teaches You
&lt;/h2&gt;

&lt;p&gt;It teaches you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How real-world architectures are segmented &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How cloud networking differs from traditional networking &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How routing enables communication &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to design secure, isolated systems &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;p&gt;This setup is commonly used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Connecting Dev and Production environments &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Separating application tiers &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi-team architectures &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microservices communication across VPCs &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsfb1taggg0mmgj9xslds.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsfb1taggg0mmgj9xslds.JPG" alt="Image of the AWS cloud console" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with Sanjeev Kumar’s team, for the &lt;strong&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;signing up&lt;/a&gt; through the link and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>beginners</category>
      <category>ec2</category>
    </item>
    <item>
      <title>Launching a Windows Server on AWS EC2</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 25 Apr 2026 19:11:05 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/launching-a-windows-server-on-aws-ec2-1kfj</link>
      <guid>https://dev.to/ikoh_sylva/launching-a-windows-server-on-aws-ec2-1kfj</guid>
      <description>&lt;p&gt;When people start learning cloud engineering, they often begin with Linux servers and for good reason.&lt;/p&gt;

&lt;p&gt;But in real-world environments, Windows servers are just as important.&lt;/p&gt;

&lt;p&gt;From enterprise applications to legacy systems and Active Directory environments, Windows workloads are everywhere. So at some point in your cloud journey, you need to answer this question:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Can you confidently deploy and securely access a Windows server in the cloud?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this guide, I’ll Walk you through exactly how to do that using AWS EC2 based on a hands-on task I completed during my cloud engineering training.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kro4335d9j8q9wfxo0w.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kro4335d9j8q9wfxo0w.JPG" alt="Image of the AWS console" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What We’ll Be Building
&lt;/h2&gt;

&lt;p&gt;In this project, we will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Launch a Windows Server EC2 instance &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy it in a public subnet &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure secure access using RDP (Remote Desktop Protocol) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Restrict access to your own public IP address &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tag your instance for proper identification &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end, you’ll have a fully running Windows server in the cloud that you can connect to remotely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This task teaches you several core cloud concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Compute provisioning (EC2) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Networking (public subnets) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security (security groups) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remote access (RDP) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resource management (tagging) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are fundamental skills every cloud engineer must master.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Launch a New EC2 Instance
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to the AWS Management Console &lt;/li&gt;
&lt;li&gt;Navigate to EC2 Dashboard &lt;/li&gt;
&lt;li&gt;Click Launch Instance &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 2: Choose Your AMI
&lt;/h2&gt;

&lt;p&gt;Select:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon Windows Server 2019 Base (or newer) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This provides a ready-to-use Windows environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Choose Instance Type
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Select t2.micro (Free Tier eligible)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good for learning and basic testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Add Name Tag
&lt;/h2&gt;

&lt;p&gt;Give your instance a clear name, e.g.:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Name: Windows-Server-Lab&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Tagging helps with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Organization &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cost tracking &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resource identification &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: Configure Networking
&lt;/h2&gt;

&lt;p&gt;Make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The instance is in a public subnet &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auto-assign Public IP is enabled &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures you can connect to it over the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Configure Security Group (Very Important)
&lt;/h2&gt;

&lt;p&gt;Create a new security group with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inbound Rule&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Type: RDP &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Port: 3389 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Source: My IP &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures:&lt;/p&gt;

&lt;p&gt;✔ Only your IP can access the server&lt;br&gt;
✔ The server is not exposed to the world&lt;/p&gt;

&lt;p&gt;This is a key real-world security practice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuy5j0fx5qfh0m1xorlbv.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuy5j0fx5qfh0m1xorlbv.JPG" alt="Image of the AWS console" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Key Pair
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create or select an existing key pair &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Download the .pem file &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll need this to decrypt the Windows password later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Launch the Instance
&lt;/h2&gt;

&lt;p&gt;Click Launch Instance and wait for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Instance state → Running &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Status checks → 2/2 passed &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 9: Connect via RDP
&lt;/h2&gt;

&lt;p&gt;Once the instance is ready:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select your instance &lt;/li&gt;
&lt;li&gt;Click Connect &lt;/li&gt;
&lt;li&gt;Choose RDP Client &lt;/li&gt;
&lt;li&gt;Download the RDP file &lt;/li&gt;
&lt;li&gt;Click Get Password &lt;/li&gt;
&lt;li&gt;Upload your .pem key &lt;/li&gt;
&lt;li&gt;Decrypt the password &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then connect using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Username: Administrator &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Password: (decrypted password) &lt;br&gt;
You’re now inside your Windows server!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Opening RDP to the world (0.0.0.0/0)&lt;/strong&gt;&lt;br&gt;
This is a major security risk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Forgetting to enable public IP&lt;/strong&gt;&lt;br&gt;
You won’t be able to connect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Losing your key pair&lt;/strong&gt;&lt;br&gt;
You won’t be able to retrieve the password.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What This Project Teaches You
&lt;/h2&gt;

&lt;p&gt;This isn’t just about launching a server.&lt;br&gt;
It teaches you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How to think about security first &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How cloud networking actually works &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to connect to real infrastructure &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to manage compute resources properly &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the foundation of real-world cloud operations.&lt;/p&gt;

&lt;p&gt;Launching a Windows EC2 instance might feel like a simple task but it introduces you to critical cloud concepts that scale into enterprise environments.&lt;/p&gt;

&lt;p&gt;If you can do this confidently, you’re already building the skills needed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Manage enterprise workloads &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support cloud infrastructure &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Work in DevOps or Cloud Engineering roles&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3dmsddye2qvgjaqaygsm.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3dmsddye2qvgjaqaygsm.JPG" alt="Image of an AWS RDP Instance" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with Sanjeev Kumar’s team, for the DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By signing up through the &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;link&lt;/a&gt; and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>aws</category>
      <category>cloudcomputing</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Managing Access the Right Way</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 18 Apr 2026 17:59:14 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/managing-access-the-right-way-1j5l</link>
      <guid>https://dev.to/ikoh_sylva/managing-access-the-right-way-1j5l</guid>
      <description>&lt;p&gt;When most people begin their cloud journey, they focus on launching servers, deploying apps, and building projects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcd5d4y6f10hksmsbl5vo.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcd5d4y6f10hksmsbl5vo.JPG" alt="Image of the aws management console" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But there’s something just as important if not more:&lt;/p&gt;

&lt;h2&gt;
  
  
  Who has access to your cloud environment… and what can they do?
&lt;/h2&gt;

&lt;p&gt;This is where AWS Identity Center comes in.&lt;/p&gt;

&lt;p&gt;During my cloud engineering training, one of the foundational tasks I completed was setting up Identity Center, creating users, and assigning permissions properly. It may seem like a small step, but in reality, it’s how secure and scalable cloud environments are built.&lt;/p&gt;

&lt;p&gt;In this article, I’ll walk you through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Why it matters &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to configure it &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to create users and assign permissions &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s get into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;In real-world environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Multiple engineers access AWS &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Teams have different responsibilities &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security is non-negotiable &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Without proper identity management:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Anyone could access sensitive resources&lt;br&gt;
❌ Permissions could be too broad&lt;br&gt;
❌ Auditing becomes difficult&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With Identity Center:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Access is controlled&lt;br&gt;
✅ Permissions are clearly defined&lt;br&gt;
✅ Security is enforced&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Enable AWS Identity Center
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to the AWS Management Console &lt;/li&gt;
&lt;li&gt;Search for “AWS Identity Center” &lt;/li&gt;
&lt;li&gt;Click Enable &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once enabled, AWS creates an Identity Center instance for your account.&lt;/p&gt;

&lt;p&gt;This is your central identity management system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Create a New User
&lt;/h2&gt;

&lt;p&gt;Next, you’ll create a user that can access AWS resources.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to Users &lt;/li&gt;
&lt;li&gt;Click Add user &lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter: &lt;br&gt;
Username &lt;br&gt;
Email address &lt;br&gt;
First and last name &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the user &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This represents a real person (or team member) who needs access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Assign a Permission Set
&lt;/h2&gt;

&lt;p&gt;Permissions define what the user can actually do.&lt;/p&gt;

&lt;p&gt;In this task, we use a predefined job function policy:&lt;/p&gt;

&lt;p&gt;SecurityAudit&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Policy Does:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Provides read-only access &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allows users to review configurations &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ideal for auditing and compliance checks &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Steps to Assign:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to AWS Accounts &lt;/li&gt;
&lt;li&gt;Select your account &lt;/li&gt;
&lt;li&gt;Click Assign users or groups &lt;/li&gt;
&lt;li&gt;Select the user you created &lt;/li&gt;
&lt;li&gt;Choose Permission Set → SecurityAudit &lt;/li&gt;
&lt;li&gt;Complete the assignment &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxrtcwdq1s7lpum8lsh8.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxxrtcwdq1s7lpum8lsh8.JPG" alt="Image of the aws management console" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How It All Comes Together
&lt;/h2&gt;

&lt;p&gt;At this point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Identity Center is enabled &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A user has been created &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Permissions have been assigned &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;p&gt;✔ The user can log in&lt;br&gt;
✔ They have controlled access&lt;br&gt;
✔ They cannot make destructive changes&lt;/p&gt;

&lt;p&gt;This is real-world security in action.&lt;/p&gt;

&lt;p&gt;This also demonstrates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Proper configuration &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Successful user creation &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Correct permission assignment &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Practices (What I Learned Along the Way)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Never Use Root Account for Daily Tasks&lt;br&gt;
Always use Identity Center or IAM users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Follow Least Privilege Principle&lt;br&gt;
Only grant permissions necessary for the task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Roles Instead of Static Credentials&lt;br&gt;
Temporary access is safer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Group Users When Scaling&lt;br&gt;
Instead of assigning permissions individually, use groups.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why This Step Is Bigger Than It Looks
&lt;/h2&gt;

&lt;p&gt;This isn’t just about clicking through AWS.&lt;/p&gt;

&lt;p&gt;It teaches you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;How organizations manage access &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How security is enforced at scale &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to think like a cloud engineer &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because in the real world:&lt;/p&gt;

&lt;p&gt;Security is not optional it’s foundational.&lt;br&gt;
Setting up AWS Identity Center and assigning permissions is one of those foundational skills that separates beginners from professionals.&lt;/p&gt;

&lt;p&gt;It’s not flashy but it’s critical and if you understand this, you’re not just learning cloud you’re learning how to build secure systems that people can trust.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8lg8v7vli347x2w07kt.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8lg8v7vli347x2w07kt.JPG" alt="Image of the aws cloud identity center" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with Sanjeev Kumar’s team, for the DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process with AltSchool Africa do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By signing up through the &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;link&lt;/a&gt; and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>cloudcomputing</category>
      <category>beginners</category>
    </item>
    <item>
      <title>AWS: Setting Up Your Account the Right Way</title>
      <dc:creator>Ikoh Sylva</dc:creator>
      <pubDate>Sat, 11 Apr 2026 13:51:14 +0000</pubDate>
      <link>https://dev.to/ikoh_sylva/aws-setting-up-your-account-the-right-way-lbb</link>
      <guid>https://dev.to/ikoh_sylva/aws-setting-up-your-account-the-right-way-lbb</guid>
      <description>&lt;p&gt;When I began my journey into cloud engineering, one of the very first steps I took was simple but incredibly important;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up my AWS account.
&lt;/h2&gt;

&lt;p&gt;It might sound basic, but this step is the gateway into the world of cloud computing. Whether you're aiming to become a Cloud Engineer, DevOps Engineer, or Solutions Architect, your AWS account is where everything begins.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Why setting up an AWS account matters &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to create one properly &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What to expect after setup &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to verify your account (as required in real training programs) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s get into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why You Need an AWS Account
&lt;/h2&gt;

&lt;p&gt;Before you can deploy servers, build applications, or experiment with cloud services, you need access to a cloud platform and AWS is one of the most widely used in the world.&lt;/p&gt;

&lt;p&gt;With an AWS account, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Launch virtual servers (EC2) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store data (S3) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build scalable applications &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Experiment with real-world cloud tools &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Practice hands-on (which is critical!) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cloud is not theory you learn it by doing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create Your AWS Account
&lt;/h2&gt;

&lt;p&gt;If you don’t already have an account, follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Go to the AWS Website&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Visit: &lt;a href="https://aws.amazon.com" rel="noopener noreferrer"&gt;https://aws.amazon.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on “Create an AWS Account”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Enter Your Details&lt;/strong&gt;&lt;br&gt;
You’ll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A valid email address (preferably personal) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A strong password &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An AWS account name (can be your name or brand) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Add Payment Information&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AWS requires a debit/credit card for verification.&lt;/p&gt;

&lt;p&gt;💡 Don’t worry:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You can stay within the Free Tier &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You won’t be charged if you use services responsibly &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Identity Verification&lt;/strong&gt;&lt;br&gt;
AWS will send a verification code to your phone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Choose a Support Plan&lt;/strong&gt;&lt;br&gt;
Select the Basic (Free) Plan&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyd1j672zop0hwg9z2a1f.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyd1j672zop0hwg9z2a1f.JPG" alt="Image of the AWS Management Console" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Log into the AWS Management Console
&lt;/h2&gt;

&lt;p&gt;Once your account is created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Go to the AWS Console &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sign in using your credentials &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll land on the AWS Management Console Dashboard this is your control center for everything in AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Tips for Beginners
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Stay Within Free Tier&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AWS Free Tier includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;EC2 (750 hours/month) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;S3 storage &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RDS usage &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Always monitor usage to avoid charges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Enable Billing Alerts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Set up alerts to avoid surprises:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Go to Billing Dashboard &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable notifications &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Use IAM (Don’t Stay on Root Account)&lt;br&gt;
After setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create an IAM user &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid using your root account daily &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a best practice used in real organizations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Step Really Means
&lt;/h2&gt;

&lt;p&gt;Setting up your AWS account might feel like a small step but it’s actually a major milestone.&lt;/p&gt;

&lt;p&gt;It means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You’ve entered the cloud ecosystem &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’re ready to build real-world projects &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You’re no longer just learning you’re doing &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every cloud engineer starts somewhere and this is where it begins.&lt;/p&gt;

&lt;p&gt;If you’ve completed this step.&lt;/p&gt;

&lt;p&gt;You now have access to one of the most powerful cloud platforms in the world.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftg5iz06acezbyoz3rcjb.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftg5iz06acezbyoz3rcjb.JPG" alt="Image of the AWS Billing Dashboard" width="800" height="536"&gt;&lt;/a&gt;&lt;br&gt;
The next step?&lt;/p&gt;

&lt;p&gt;Start building. Break things. Fix them. Learn. Repeat.&lt;/p&gt;

&lt;p&gt;That’s how you grow. If you’ve just set up your AWS account:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Drop a comment or share your experience &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let me know what you plan to build first &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m also excited to share that I’ve been able to secure a special discount, in partnership with &lt;strong&gt;Sanjeev Kumar’s team&lt;/strong&gt;, for the DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/p&gt;

&lt;p&gt;For those who may not be familiar, Sanjeev Kumar brings over 20 years of hands-on experience across multiple domains and every phase of product delivery. He is known for his strong architectural mindset, with a deep focus on Automation, DevOps, Cloud, and Security.&lt;/p&gt;

&lt;p&gt;Sanjeev has extensive expertise in technology assessment, working closely with senior leadership, architects, and diverse software delivery teams to build scalable and secure systems. Beyond industry practice, he is also an active educator, running a YouTube channel dedicated to helping professionals successfully transition into DevOps and Cloud careers.&lt;/p&gt;

&lt;p&gt;This is a great opportunity for anyone looking to level up their DevOps/Cloud skills with real-world mentorship and career guidance.&lt;/p&gt;

&lt;p&gt;Do refer below for the link with a dedicated discount automatically applied at checkout;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://topmate.io/cloud/1541247?utm_source=sales_sylvanus&amp;amp;utm_medium=calling&amp;amp;utm_content=sales_42261" rel="noopener noreferrer"&gt;DevOps &amp;amp; Cloud Job Placement / Mentorship Program.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you also found this interesting and would love to take the next steps in the application process do use my referral link below;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;Apply here&lt;/a&gt; or use this Code: W2jBG8 during the registration process and by so doing, you will be supporting me and also getting a discount!&lt;/p&gt;

&lt;p&gt;Special Offer: By &lt;a href="https://portal.altschoolafrica.com/auth/signin?ref=W2jBG8" rel="noopener noreferrer"&gt;signing up&lt;/a&gt; through the link and using the code shared, you’ll receive a 10% discount!&lt;/p&gt;

&lt;p&gt;Don’t miss out on this opportunity to transform your future and also save while doing it! Let’s grow together in the tech space. Also feel free to reach out if you need assistance or clarity regarding the program.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxwplexi3mbapob6kfy7.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhxwplexi3mbapob6kfy7.JPG" alt="Image of the AWS Management Console" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m Ikoh Sylva, a passionate cloud computing enthusiast with hands-on experience in AWS. I’m documenting my cloud journey here from a beginner’s perspective, aiming to inspire others along the way.&lt;/p&gt;

&lt;p&gt;If you find my contents helpful, please like and follow my posts, and consider sharing this article with anyone starting their own cloud journey.&lt;/p&gt;

&lt;p&gt;Let’s connect on social media. I’d love to engage and exchange ideas with you!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linkedin.com/in/ikoh-sylva-73a208185" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;   &lt;a href="https://www.facebook.com/Ikoh.Silver" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;    &lt;a href="https://www.x.com/Ikoh_Sylva" rel="noopener noreferrer"&gt;X&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>aws</category>
      <category>cloudcomputing</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
