<?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: Vishal Patil</title>
    <description>The latest articles on DEV Community by Vishal Patil (@vishal_patil_aws).</description>
    <link>https://dev.to/vishal_patil_aws</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%2F4079087%2F54141cc3-1a86-4fda-bc0d-279396810a1e.png</url>
      <title>DEV Community: Vishal Patil</title>
      <link>https://dev.to/vishal_patil_aws</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vishal_patil_aws"/>
    <language>en</language>
    <item>
      <title>AWS S3 Bucket Versioning: Protect Your Data from Accidental Deletes and Overwrites</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Wed, 04 Nov 2026 03:45:39 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/aws-s3-bucket-versioning-protect-your-data-from-accidental-deletes-and-overwrites-2bld</link>
      <guid>https://dev.to/vishal_patil_aws/aws-s3-bucket-versioning-protect-your-data-from-accidental-deletes-and-overwrites-2bld</guid>
      <description>&lt;p&gt;A hands-on guide to enabling S3 versioning, recovering deleted files, and keeping costs under control with lifecycle rules."&lt;/p&gt;

&lt;h2&gt;
  
  
  tags: aws, s3, cloud, beginners
&lt;/h2&gt;

&lt;p&gt;Overwriting the wrong file or deleting an important object in S3 is easy to do, and by default it is permanent. &lt;strong&gt;S3 Versioning&lt;/strong&gt; fixes this. It keeps every version of every object in your bucket, so you can recover from mistakes and from application failures. In this post I enable versioning, test it, and recover a deleted file.&lt;/p&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney
&lt;/h1&gt;

&lt;h2&gt;
  
  
  📦 What is S3 Versioning?
&lt;/h2&gt;

&lt;p&gt;Versioning is a bucket-level feature that keeps multiple variants of an object in the same bucket. Every upload of the same key creates a new version with its own unique &lt;strong&gt;Version ID&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A bucket is always in one of three states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unversioned&lt;/strong&gt; (the default)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Versioning-enabled&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Versioning-suspended&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Once you enable versioning, you cannot go back to unversioned. You can only suspend it, and existing versions are kept.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ✅ Why use it?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recover from accidental deletion:&lt;/strong&gt; a delete only adds a &lt;em&gt;delete marker&lt;/em&gt;, and the data stays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recover from accidental overwrites:&lt;/strong&gt; older versions are still there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep a history:&lt;/strong&gt; useful for audits and rollbacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safer backups:&lt;/strong&gt; a good protection layer against human error and some application bugs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🖱️ Hands-on: Enable versioning in the console
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create a bucket
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;strong&gt;S3&lt;/strong&gt; console and click &lt;strong&gt;Create bucket&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter a globally unique bucket name, such as &lt;code&gt;vishal-versioning-demo-123&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Choose your region and keep &lt;strong&gt;Block all public access&lt;/strong&gt; on.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create bucket&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Enable versioning
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open your bucket and go to the &lt;strong&gt;Properties&lt;/strong&gt; tab.&lt;/li&gt;
&lt;li&gt;Find &lt;strong&gt;Bucket Versioning&lt;/strong&gt; and click &lt;strong&gt;Edit&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Enable&lt;/strong&gt; and click &lt;strong&gt;Save changes&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Upload and overwrite a file
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a file &lt;code&gt;demo.txt&lt;/code&gt; containing &lt;code&gt;Version 1&lt;/code&gt; and upload it.&lt;/li&gt;
&lt;li&gt;Change the content to &lt;code&gt;Version 2&lt;/code&gt; and upload it again with the same name.&lt;/li&gt;
&lt;li&gt;Open the &lt;strong&gt;Objects&lt;/strong&gt; tab and turn on the &lt;strong&gt;List versions&lt;/strong&gt; toggle.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You will see two versions of &lt;code&gt;demo.txt&lt;/code&gt;, each with its own Version ID. The latest one is the &lt;strong&gt;current version&lt;/strong&gt;, and the other is a &lt;strong&gt;noncurrent version&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Delete and recover
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Turn &lt;strong&gt;List versions&lt;/strong&gt; off, select &lt;code&gt;demo.txt&lt;/code&gt; and click &lt;strong&gt;Delete&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The file seems to disappear. Turn &lt;strong&gt;List versions&lt;/strong&gt; back on.&lt;/li&gt;
&lt;li&gt;You will see a &lt;strong&gt;Delete marker&lt;/strong&gt; on top of your versions. Your data is safe.&lt;/li&gt;
&lt;li&gt;Select the delete marker and delete it. &lt;code&gt;demo.txt&lt;/code&gt; comes back.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To remove a version permanently, delete it by its specific Version ID.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⌨️ Hands-on: Using the AWS CLI
&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;# Enable versioning&lt;/span&gt;
aws s3api put-bucket-versioning &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bucket&lt;/span&gt; vishal-versioning-demo-123 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--versioning-configuration&lt;/span&gt; &lt;span class="nv"&gt;Status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Enabled

&lt;span class="c"&gt;# Check the status&lt;/span&gt;
aws s3api get-bucket-versioning &lt;span class="nt"&gt;--bucket&lt;/span&gt; vishal-versioning-demo-123

&lt;span class="c"&gt;# List all versions and delete markers&lt;/span&gt;
aws s3api list-object-versions &lt;span class="nt"&gt;--bucket&lt;/span&gt; vishal-versioning-demo-123

&lt;span class="c"&gt;# Download a specific version&lt;/span&gt;
aws s3api get-object &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bucket&lt;/span&gt; vishal-versioning-demo-123 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--key&lt;/span&gt; demo.txt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--version-id&lt;/span&gt; &amp;lt;VERSION_ID&amp;gt; demo-old.txt

&lt;span class="c"&gt;# Permanently delete one specific version&lt;/span&gt;
aws s3api delete-object &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bucket&lt;/span&gt; vishal-versioning-demo-123 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--key&lt;/span&gt; demo.txt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--version-id&lt;/span&gt; &amp;lt;VERSION_ID&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  💡 Things to know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; every version is stored and billed as a separate object, so storage grows with each update.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifecycle rules:&lt;/strong&gt; use them to expire noncurrent versions after N days, or move them to a cheaper storage class. This keeps costs under control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Objects uploaded before versioning:&lt;/strong&gt; they get the Version ID &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MFA Delete:&lt;/strong&gt; an optional extra protection that requires MFA to permanently delete a version or change the versioning state. Only the bucket owner's root account can enable it, and only through the CLI or API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replication:&lt;/strong&gt; Cross-Region Replication requires versioning on both buckets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🏆 Best practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Turn versioning on for buckets that hold important or hard-to-recreate data.&lt;/li&gt;
&lt;li&gt;Add a lifecycle rule to clean up old noncurrent versions.&lt;/li&gt;
&lt;li&gt;Restrict who can permanently delete versions with IAM and bucket policies.&lt;/li&gt;
&lt;li&gt;Consider MFA Delete for critical buckets.&lt;/li&gt;
&lt;li&gt;Monitor storage growth in the S3 console and in billing.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;A versioned bucket is not empty until &lt;strong&gt;all versions and delete markers&lt;/strong&gt; are removed. Use &lt;strong&gt;Empty&lt;/strong&gt; in the console, then delete the bucket, so you don't pay for leftover data.&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Key learnings
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Versioning turns a permanent delete into a recoverable one.&lt;/li&gt;
&lt;li&gt;A delete on a versioned bucket adds a delete marker, and the data stays in the bucket.&lt;/li&gt;
&lt;li&gt;Lifecycle rules are the best way to keep versioning affordable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤝 Connect with me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;Vishal Patil&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;VishalPatil-DevOps-AWS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;dev.to: &lt;a href="https://dev.to/vishal_patil_aws"&gt;@vishal_patil_aws&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this helped you, drop a ❤️ and tell me how you use S3 versioning in the comments!&lt;/p&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney #AWS #S3 #CloudStorage #DataProtection
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Built a CI/CD Pipeline with Jenkins, SonarQube, Docker &amp; Kubernetes on AWS EC2</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Tue, 03 Nov 2026 03:26:02 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/i-built-a-cicd-pipeline-with-jenkins-sonarqube-docker-kubernetes-on-aws-ec2-5817</link>
      <guid>https://dev.to/vishal_patil_aws/i-built-a-cicd-pipeline-with-jenkins-sonarqube-docker-kubernetes-on-aws-ec2-5817</guid>
      <description>&lt;p&gt;A step-by-step guide to automating build, code quality checks, Docker image push and Kubernetes deployment using Jenkins on AWS EC2."&lt;/p&gt;

&lt;h2&gt;
  
  
  tags: aws, devops, kubernetes, jenkins
&lt;/h2&gt;

&lt;p&gt;Shipping code by hand is slow and easy to get wrong. So I built a complete CI/CD pipeline on AWS: every push to GitHub is compiled, scanned for code quality, packaged, containerized, pushed to Docker Hub and deployed to Kubernetes automatically.&lt;/p&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🏗️ Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub → Jenkins (EC2) → Maven → SonarQube → Docker → Docker Hub → Kubernetes&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pipeline stages
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Declarative: Tool Install&lt;/li&gt;
&lt;li&gt;Git Checkout&lt;/li&gt;
&lt;li&gt;Code Compile&lt;/li&gt;
&lt;li&gt;SonarQube Analysis&lt;/li&gt;
&lt;li&gt;Maven Build&lt;/li&gt;
&lt;li&gt;Docker Build&lt;/li&gt;
&lt;li&gt;Docker Image Push&lt;/li&gt;
&lt;li&gt;Deploy to Kubernetes&lt;/li&gt;
&lt;li&gt;Declarative: Post Actions&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Tools used
&lt;/h3&gt;

&lt;p&gt;AWS EC2, Jenkins, Maven, SonarQube, Docker, Docker Hub, Kubernetes (kubectl), GitHub&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Launch EC2 instances
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Launch an Ubuntu EC2 instance (t2.medium or larger) for Jenkins and SonarQube.&lt;/li&gt;
&lt;li&gt;Launch instances for your Kubernetes cluster (or use EKS).&lt;/li&gt;
&lt;li&gt;Open these ports in the Security Group:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8080&lt;/td&gt;
&lt;td&gt;Jenkins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9000&lt;/td&gt;
&lt;td&gt;SonarQube&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6443&lt;/td&gt;
&lt;td&gt;Kubernetes API (restrict to the Jenkins server IP)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30000-32767&lt;/td&gt;
&lt;td&gt;NodePort range for your app&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Avoid opening ports to &lt;code&gt;0.0.0.0/0&lt;/code&gt; unless you have to. Restrict them to your own IP wherever possible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 2: Install Jenkins
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;openjdk-17-jdk &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="c"&gt;# Add the Jenkins repository, then:&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;jenkins &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://&amp;lt;EC2-Public-IP&amp;gt;:8080&lt;/code&gt;, unlock Jenkins with the initial admin password and install the suggested plugins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Install Docker, Maven and kubectl
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;docker.io maven &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker jenkins
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart jenkins
&lt;span class="c"&gt;# install kubectl as per the official Kubernetes docs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding &lt;code&gt;jenkins&lt;/code&gt; to the &lt;code&gt;docker&lt;/code&gt; group lets pipeline builds run Docker commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Set up SonarQube
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; sonarqube &lt;span class="nt"&gt;-p&lt;/span&gt; 9000:9000 sonarqube:lts-community
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Log in at &lt;code&gt;http://&amp;lt;EC2-IP&amp;gt;:9000&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Generate a token under &lt;strong&gt;My Account → Security&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Create a project and note its project key.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 5: Configure Jenkins
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Plugins:&lt;/strong&gt; SonarQube Scanner, Docker Pipeline, Kubernetes CLI, Pipeline Stage View, Maven Integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credentials&lt;/strong&gt; (Manage Jenkins → Credentials):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dockerhub-cred&lt;/code&gt;: Docker Hub username and password&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sonar-token&lt;/code&gt;: the SonarQube token&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;k8s-config&lt;/code&gt;: your kubeconfig file, as a Secret file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tools&lt;/strong&gt; (Manage Jenkins → Tools): add Maven and JDK.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SonarQube server&lt;/strong&gt; (Manage Jenkins → System): add the server URL and token.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Write the Jenkinsfile
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;pipeline&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;maven&lt;/span&gt; &lt;span class="s1"&gt;'maven3'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;IMAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your-dockerhub-user/your-app"&lt;/span&gt;
        &lt;span class="n"&gt;TAG&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${BUILD_NUMBER}"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;stages&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Git Checkout'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;git&lt;/span&gt; &lt;span class="nl"&gt;branch:&lt;/span&gt; &lt;span class="s1"&gt;'main'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;url:&lt;/span&gt; &lt;span class="s1"&gt;'https://github.com/&amp;lt;you&amp;gt;/&amp;lt;repo&amp;gt;.git'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Code Compile'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'mvn compile'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SonarQube Analysis'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;withSonarQubeEnv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sonar'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'mvn sonar:sonar'&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Maven Build'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'mvn clean package -DskipTests'&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Docker Build'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"docker build -t $IMAGE:$TAG ."&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Docker Image Push'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;withCredentials&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="n"&gt;usernamePassword&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;credentialsId:&lt;/span&gt; &lt;span class="s1"&gt;'dockerhub-cred'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="nl"&gt;usernameVariable:&lt;/span&gt; &lt;span class="s1"&gt;'U'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;passwordVariable:&lt;/span&gt; &lt;span class="s1"&gt;'P'&lt;/span&gt;&lt;span class="o"&gt;)])&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'echo $P | docker login -u $U --password-stdin'&lt;/span&gt;
                    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"docker push $IMAGE:$TAG"&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Deploy to Kubernetes'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;withKubeConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;credentialsId:&lt;/span&gt; &lt;span class="s1"&gt;'k8s-config'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s2"&gt;"sed -i 's|IMAGE_TAG|$TAG|g' k8s/deployment.yaml"&lt;/span&gt;
                    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'kubectl apply -f k8s/deployment.yaml'&lt;/span&gt;
                    &lt;span class="n"&gt;sh&lt;/span&gt; &lt;span class="s1"&gt;'kubectl apply -f k8s/service.yaml'&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7: Kubernetes manifests
&lt;/h2&gt;

&lt;p&gt;Keep these in a &lt;code&gt;k8s/&lt;/code&gt; folder in your repo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;deployment.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-dockerhub-user/your-app:IMAGE_TAG&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;service.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app-svc&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodePort&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-app&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
      &lt;span class="na"&gt;nodePort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 8: Run the pipeline
&lt;/h2&gt;

&lt;p&gt;Create a &lt;strong&gt;Pipeline&lt;/strong&gt; job, point it at your repo's Jenkinsfile and click &lt;strong&gt;Build Now&lt;/strong&gt;. The Stage View shows each stage turning green, and the SonarQube Quality Gate shows &lt;strong&gt;Passed&lt;/strong&gt; when your code meets the quality rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Troubleshooting: when "Deploy to Kubernetes" fails
&lt;/h2&gt;

&lt;p&gt;My first builds (#25, #26 and #27) passed every stage until &lt;strong&gt;Deploy to Kubernetes&lt;/strong&gt;, then failed. Build #25 failed in under a second, while #26 and #27 ran for about 3 minutes before failing. Build #28 passed, and the deploy stage took about 38 seconds.&lt;/p&gt;

&lt;p&gt;Since everything before the deploy stage worked, the problem was between Jenkins and the cluster. A failure after about 3 minutes usually points to a connection timeout, and a near-instant failure usually points to a credential or config error. Things to check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kubeconfig credential:&lt;/strong&gt; is it uploaded correctly, and does the &lt;code&gt;withKubeConfig&lt;/code&gt; ID match?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network access:&lt;/strong&gt; can the Jenkins server reach the cluster API on port 6443? Check the Security Group and the server IP in the kubeconfig.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual test:&lt;/strong&gt; SSH into the Jenkins server and run &lt;code&gt;kubectl get nodes&lt;/code&gt; as the &lt;code&gt;jenkins&lt;/code&gt; user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manifest errors:&lt;/strong&gt; check the YAML, image name and tag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pod state:&lt;/strong&gt; run &lt;code&gt;kubectl get pods&lt;/code&gt; and &lt;code&gt;kubectl describe pod&lt;/code&gt; to spot image pull errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📚 Key learnings
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Automating the path from commit to deployment removes manual mistakes.&lt;/li&gt;
&lt;li&gt;SonarQube's Quality Gate catches bad code before it ships.&lt;/li&gt;
&lt;li&gt;Tagging images with the build number makes every deployment traceable and easy to roll back.&lt;/li&gt;
&lt;li&gt;Most pipeline failures come from credentials, permissions and networking, so check those first.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🚀 What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add a GitHub webhook so builds trigger on every push.&lt;/li&gt;
&lt;li&gt;Move to Amazon EKS and Amazon ECR.&lt;/li&gt;
&lt;li&gt;Add Slack or SNS notifications for build status.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤝 Connect with me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;Vishal Patil&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;VishalPatil-DevOps-AWS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;dev.to: &lt;a href="https://dev.to/vishal_patil_aws"&gt;@vishal_patil_aws&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this helped you, drop a ❤️ and share what you're building in the comments!&lt;/p&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney #AWS #DevOps #Jenkins #Kubernetes #Docker #SonarQube #CICD
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>docker</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Building a Highly Available 3-Tier Web App on AWS with VPC, EC2, ALB and Aurora</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Mon, 02 Nov 2026 07:40:11 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/building-a-highly-available-3-tier-web-app-on-aws-with-vpc-ec2-alb-and-aurora-3f1k</link>
      <guid>https://dev.to/vishal_patil_aws/building-a-highly-available-3-tier-web-app-on-aws-with-vpc-ec2-alb-and-aurora-3f1k</guid>
      <description>&lt;p&gt;A hands-on walkthrough of building a web, app, and database tier across two Availability Zones on AWS.&lt;br&gt;
tags: aws, devops, cloud, beginners&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Vishal Patil | &lt;strong&gt;Project Manager:&lt;/strong&gt; Ulhas Narwade&lt;/p&gt;
&lt;h1&gt;
  
  
  vishalcloudjourney
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Early in my AWS learning, I practiced with single services: an EC2 instance here, an S3 bucket there. Those taught me the basics, but not how real applications are built. Production systems are layered, with clear security boundaries and a plan for failure.&lt;/p&gt;

&lt;p&gt;So I built a &lt;strong&gt;3-tier web application on AWS&lt;/strong&gt; from scratch, with a web tier, an application tier, and a database tier. Each tier has its own subnets and security rules, and everything is spread across &lt;strong&gt;two Availability Zones&lt;/strong&gt; so one data center failing doesn't take the app down.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Is a 3-Tier Architecture?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Network placement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Serves the React UI, forwards API calls&lt;/td&gt;
&lt;td&gt;Public subnets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Application&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Business logic, database access&lt;/td&gt;
&lt;td&gt;Private subnets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Persistent data storage&lt;/td&gt;
&lt;td&gt;Private subnets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Why use it?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only the web tier faces the internet&lt;/li&gt;
&lt;li&gt;Each tier scales independently&lt;/li&gt;
&lt;li&gt;You can update one layer without touching the others&lt;/li&gt;
&lt;li&gt;A failure in one layer stays contained&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A custom &lt;strong&gt;VPC&lt;/strong&gt; across two Availability Zones (AZ1 and AZ2)&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Internet Gateway&lt;/strong&gt; for internet connectivity&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;external Application Load Balancer&lt;/strong&gt; for user traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web tier:&lt;/strong&gt; two EC2 instances in public subnets, one per AZ&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;internal Application Load Balancer&lt;/strong&gt; between the web and app tiers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App tier:&lt;/strong&gt; two EC2 instances in private subnets, one per AZ&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database tier:&lt;/strong&gt; an &lt;strong&gt;Amazon Aurora&lt;/strong&gt; primary (writer) and a &lt;strong&gt;Read Replica&lt;/strong&gt; in the other AZ, both private&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;NAT Gateway&lt;/strong&gt; so private instances can download packages without being exposed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Traffic flow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user opens the external ALB's DNS name.&lt;/li&gt;
&lt;li&gt;The request passes through the Internet Gateway to the external ALB.&lt;/li&gt;
&lt;li&gt;The ALB forwards it to a healthy web tier instance.&lt;/li&gt;
&lt;li&gt;Nginx serves the React UI and proxies API calls to the internal ALB.&lt;/li&gt;
&lt;li&gt;The internal ALB routes them to a healthy app tier instance.&lt;/li&gt;
&lt;li&gt;The app tier reads from and writes to Aurora.&lt;/li&gt;
&lt;li&gt;The response returns along the same path.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I built everything in the &lt;strong&gt;Asia Pacific (Mumbai) &lt;code&gt;ap-south-1&lt;/code&gt;&lt;/strong&gt; region.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Create the Network
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VPC&lt;/strong&gt; with a CIDR block such as &lt;code&gt;10.0.0.0/16&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Six subnets&lt;/strong&gt;, two per tier, one in each AZ (names like &lt;code&gt;web-public-1a&lt;/code&gt;, &lt;code&gt;app-private-1a&lt;/code&gt;, &lt;code&gt;db-private-1a&lt;/code&gt; help a lot)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internet Gateway&lt;/strong&gt; attached to the VPC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public route table:&lt;/strong&gt; &lt;code&gt;0.0.0.0/0&lt;/code&gt; to the Internet Gateway, for the public subnets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NAT Gateway&lt;/strong&gt; in a public subnet with an Elastic IP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private route table:&lt;/strong&gt; &lt;code&gt;0.0.0.0/0&lt;/code&gt; to the NAT Gateway, for the private subnets&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 2: Configure Security Groups
&lt;/h2&gt;

&lt;p&gt;I chained security groups so each tier only trusts the tier in front of it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Security group&lt;/th&gt;
&lt;th&gt;Inbound rule&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;External ALB SG&lt;/td&gt;
&lt;td&gt;HTTP 80&lt;/td&gt;
&lt;td&gt;Anywhere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web tier SG&lt;/td&gt;
&lt;td&gt;HTTP 80&lt;/td&gt;
&lt;td&gt;External ALB SG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internal ALB SG&lt;/td&gt;
&lt;td&gt;HTTP 80&lt;/td&gt;
&lt;td&gt;Web tier SG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App tier SG&lt;/td&gt;
&lt;td&gt;App port (e.g. 3200)&lt;/td&gt;
&lt;td&gt;Internal ALB SG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database SG&lt;/td&gt;
&lt;td&gt;3306&lt;/td&gt;
&lt;td&gt;App tier SG&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For admin access I used SSH from my own IP on the web tier as a jump host. In production, use &lt;strong&gt;AWS Systems Manager Session Manager&lt;/strong&gt; instead.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: Build the Database Tier
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;strong&gt;DB subnet group&lt;/strong&gt; with the two private database subnets.&lt;/li&gt;
&lt;li&gt;Launch an &lt;strong&gt;Aurora (MySQL-compatible)&lt;/strong&gt; cluster with a writer in AZ1 and a reader in AZ2, using the database security group, with public access set to &lt;strong&gt;No&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;From an app instance, connect to the writer endpoint and create the schema:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;webappdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="n"&gt;webappdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;transactions&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&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 4: Build the Application Tier
&lt;/h2&gt;

&lt;p&gt;Launch two Amazon Linux EC2 instances in the private app subnets and install the tools:&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="nb"&gt;sudo &lt;/span&gt;yum update &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;mysql &lt;span class="nt"&gt;-y&lt;/span&gt;
curl &lt;span class="nt"&gt;-o-&lt;/span&gt; https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
nvm &lt;span class="nb"&gt;install &lt;/span&gt;16
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set the database details in the backend config (placeholders only, never publish real credentials):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;DB_HOST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;aurora-writer-endpoint&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;DB_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;db-username&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;DB_PWD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;db-password&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;DB_DATABASE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webappdb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the service with PM2 so it survives crashes and reboots:&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="nb"&gt;cd&lt;/span&gt; ~/app-tier &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install
&lt;/span&gt;pm2 start index.js
pm2 startup &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pm2 save
curl http://localhost:3200/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a target group with a &lt;code&gt;/health&lt;/code&gt; check, register both instances, and create the &lt;strong&gt;internal ALB&lt;/strong&gt; across the private app subnets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Build the Web Tier
&lt;/h2&gt;

&lt;p&gt;On two EC2 instances in the public subnets, build the React app and install Nginx:&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="nb"&gt;cd&lt;/span&gt; ~/web-tier
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run build
&lt;span class="nb"&gt;sudo &lt;/span&gt;amazon-linux-extras &lt;span class="nb"&gt;install &lt;/span&gt;nginx1 &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nginx serves the build and reverse-proxies API calls to the internal ALB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/home/ec2-user/web-tier/build&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="n"&gt;/index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://&amp;lt;internal-alb-dns-name&amp;gt;:80/&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, create a web target group (health check on &lt;code&gt;/&lt;/code&gt;), register both instances, and create the &lt;strong&gt;internet-facing ALB&lt;/strong&gt; across the public subnets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Test the Application
&lt;/h2&gt;

&lt;p&gt;I opened the external load balancer's DNS name:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Home page:&lt;/strong&gt; "AWS 3-TIER WEB APP DEMO" loaded with the architecture diagram, confirming the web tier and external ALB worked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database page:&lt;/strong&gt; the "AURORA DATABASE DEMO PAGE" listed records (ID, Amount, Description) with ADD and DEL buttons. I added a record, refreshed, and it persisted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That one page proved the full chain: browser, external ALB, web tier, internal ALB, app tier, Aurora.&lt;/p&gt;

&lt;h2&gt;
  
  
  High Availability in Practice
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An instance fails:&lt;/strong&gt; health checks remove it and the other instance serves users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An entire AZ fails:&lt;/strong&gt; each tier has an instance in the second AZ, so traffic continues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Aurora primary fails:&lt;/strong&gt; the read replica can be promoted to writer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try it: stop one web instance and keep refreshing the page. The site stays up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges and Fixes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Unhealthy targets:&lt;/strong&gt; wrong health check path and a missing security group rule. Check path, port, and security group, in that order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;403 Forbidden from Nginx:&lt;/strong&gt; Nginx couldn't read the build folder. Fixing permissions and the &lt;code&gt;root&lt;/code&gt; path solved it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend couldn't reach the backend:&lt;/strong&gt; &lt;code&gt;proxy_pass&lt;/code&gt; pointed to the wrong address. Use the internal ALB DNS name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database connection errors:&lt;/strong&gt; wrong endpoint and a missing rule for port 3306 from the app tier SG.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My best debugging habit: &lt;strong&gt;test one tier at a time, bottom up.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Learnings
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Only the web tier is public, and chained security groups limit each tier's trust.&lt;/li&gt;
&lt;li&gt;Load balancer health checks are the basis of self-healing.&lt;/li&gt;
&lt;li&gt;Subnet and route table design prevents most networking headaches.&lt;/li&gt;
&lt;li&gt;Nginx as a reverse proxy gives the browser one endpoint while traffic routes internally.&lt;/li&gt;
&lt;li&gt;Secrets don't belong in code. Use Secrets Manager or Parameter Store in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cost and Clean-Up
&lt;/h2&gt;

&lt;p&gt;Delete in this order to avoid charges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Both load balancers and target groups&lt;/li&gt;
&lt;li&gt;EC2 instances&lt;/li&gt;
&lt;li&gt;The Aurora cluster (reader first, then writer)&lt;/li&gt;
&lt;li&gt;The NAT Gateway, then release its Elastic IP&lt;/li&gt;
&lt;li&gt;Subnets, route tables, Internet Gateway, security groups, and finally the VPC&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The NAT Gateway, Aurora, and load balancers cost the most. Set up an &lt;strong&gt;AWS Budget&lt;/strong&gt; alert before you start.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Auto Scaling Groups for the web and app tiers&lt;/li&gt;
&lt;li&gt;HTTPS with AWS Certificate Manager&lt;/li&gt;
&lt;li&gt;Route 53 for a friendly domain name&lt;/li&gt;
&lt;li&gt;AWS WAF in front of the external ALB&lt;/li&gt;
&lt;li&gt;CloudWatch dashboards and alarms&lt;/li&gt;
&lt;li&gt;CloudFormation or Terraform to automate the whole build&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Studying VPC, EC2, ELB, security groups, and Aurora separately gave me pieces of a puzzle. Wiring them into one working system showed me how they depend on each other and why networking, security, and availability decisions matter. If you're learning AWS, build a project like this end to end. You'll learn more from debugging it than from any slide deck.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgement
&lt;/h2&gt;

&lt;p&gt;This project was completed under the guidance of my project manager, &lt;strong&gt;Ulhas Narwade Sir&lt;/strong&gt;. His direction, reviews, and support helped me understand how a real-world 3-tier architecture is planned, built, and tested on AWS.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Written by:&lt;/strong&gt; Vishal Patil&lt;br&gt;
&lt;strong&gt;Project Manager:&lt;/strong&gt; Ulhas Narwade&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect with me:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;vishalpatil-devops-aws&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;dev.to: &lt;a href="https://dev.to/vishal_patil_aws"&gt;@vishal_patil_aws&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;VishalPatil-DevOps-AWS&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney #AWS #3TierArchitecture #AmazonAurora #ElasticLoadBalancing #VPC
&lt;/h1&gt;

</description>
      <category>architecture</category>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Secure Amazon S3 Buckets Using IAM Policies and Bucket Policies</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Sun, 01 Nov 2026 04:20:16 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/secure-amazon-s3-buckets-using-iam-policies-and-bucket-policies-40bh</link>
      <guid>https://dev.to/vishal_patil_aws/secure-amazon-s3-buckets-using-iam-policies-and-bucket-policies-40bh</guid>
      <description>&lt;p&gt;Introduction&lt;/p&gt;

&lt;p&gt;Amazon S3 is one of the most widely used AWS services, and also one of the most common sources of data leaks. Almost every S3 breach in the news comes down to one thing: a misconfigured access policy.&lt;/p&gt;

&lt;p&gt;In this article, I'll explain the two main ways of controlling access to S3, IAM policies and bucket policies, show when to use each, and walk through a hands-on example you can try in your own account.&lt;/p&gt;

&lt;p&gt;How S3 Access Is Evaluated&lt;/p&gt;

&lt;p&gt;Before writing any policy, it helps to know how AWS decides whether a request is allowed:&lt;/p&gt;

&lt;p&gt;Everything is denied by default.&lt;br&gt;
An explicit Allow in a relevant policy grants access.&lt;br&gt;
An explicit Deny always wins, no matter what else says Allow.&lt;br&gt;
For requests within the same account, access is granted if either the IAM policy or the bucket policy allows it (and nothing denies it).&lt;/p&gt;

&lt;p&gt;Remember this rule: Explicit Deny &amp;gt; Allow &amp;gt; Default Deny.&lt;/p&gt;

&lt;p&gt;IAM Policies vs Bucket Policies&lt;br&gt;
Feature IAM Policy  Bucket Policy&lt;br&gt;
Attached to IAM user, group, or role    The S3 bucket&lt;br&gt;
Answers the question    "What can this identity do?"    "Who can access this bucket?"&lt;br&gt;
Has a Principal element No  Yes&lt;br&gt;
Cross-account access    Needs help from the other side  Supported directly&lt;br&gt;
Best for    Managing permissions for your users and roles   Bucket-wide rules, cross-account access, enforcing conditions&lt;br&gt;
Size limit  2 KB (users), 6 KB (groups), 10 KB (roles)  20 KB&lt;/p&gt;

&lt;p&gt;Simple way to remember it:&lt;/p&gt;

&lt;p&gt;IAM policy = identity-based ("what can I do?")&lt;br&gt;
Bucket policy = resource-based ("who can touch this bucket?")&lt;br&gt;
Hands-On: Secure a Bucket Step by Step&lt;br&gt;
Step 1: Create a Private Bucket&lt;br&gt;
Open the S3 console and choose Create bucket.&lt;br&gt;
Give it a unique name, for example vishal-secure-demo-bucket.&lt;br&gt;
Keep Block all public access turned ON.&lt;br&gt;
Enable Bucket Versioning.&lt;br&gt;
Enable Default encryption (SSE-S3 or SSE-KMS).&lt;br&gt;
Choose Create bucket.&lt;/p&gt;

&lt;p&gt;Tip: Block Public Access is your first line of defense. Leave it on unless you have a very specific reason to turn it off.&lt;/p&gt;

&lt;p&gt;Step 2: Create an IAM Policy (Least Privilege)&lt;/p&gt;

&lt;p&gt;Let's give a user read and write access to only one bucket, nothing more.&lt;/p&gt;

&lt;p&gt;json&lt;br&gt;
{&lt;br&gt;
  "Version": "2012-10-17",&lt;br&gt;
  "Statement": [&lt;br&gt;
    {&lt;br&gt;
      "Sid": "ListBucket",&lt;br&gt;
      "Effect": "Allow",&lt;br&gt;
      "Action": "s3:ListBucket",&lt;br&gt;
      "Resource": "arn:aws:s3:::vishal-secure-demo-bucket"&lt;br&gt;
    },&lt;br&gt;
    {&lt;br&gt;
      "Sid": "ReadWriteObjects",&lt;br&gt;
      "Effect": "Allow",&lt;br&gt;
      "Action": [&lt;br&gt;
        "s3:GetObject",&lt;br&gt;
        "s3:PutObject"&lt;br&gt;
      ],&lt;br&gt;
      "Resource": "arn:aws:s3:::vishal-secure-demo-bucket/*"&lt;br&gt;
    }&lt;br&gt;
  ]&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Why two statements? s3:ListBucket applies to the bucket itself, while GetObject and PutObject apply to the objects inside it (/*). This is a very common mistake for beginners.&lt;/p&gt;

&lt;p&gt;To apply it:&lt;/p&gt;

&lt;p&gt;Go to IAM → Policies → Create policy → JSON and paste the policy.&lt;br&gt;
Name it S3-DemoBucket-ReadWrite.&lt;br&gt;
Attach it to a user, group, or (better) a role.&lt;br&gt;
Step 3: Add a Bucket Policy to Enforce HTTPS&lt;/p&gt;

&lt;p&gt;Now let's add a rule at the bucket level. This policy denies any request that doesn't use HTTPS:&lt;/p&gt;

&lt;p&gt;json&lt;br&gt;
{&lt;br&gt;
  "Version": "2012-10-17",&lt;br&gt;
  "Statement": [&lt;br&gt;
    {&lt;br&gt;
      "Sid": "DenyInsecureTransport",&lt;br&gt;
      "Effect": "Deny",&lt;br&gt;
      "Principal": "&lt;em&gt;",&lt;br&gt;
      "Action": "s3:&lt;/em&gt;",&lt;br&gt;
      "Resource": [&lt;br&gt;
        "arn:aws:s3:::vishal-secure-demo-bucket",&lt;br&gt;
        "arn:aws:s3:::vishal-secure-demo-bucket/*"&lt;br&gt;
      ],&lt;br&gt;
      "Condition": {&lt;br&gt;
        "Bool": {&lt;br&gt;
          "aws:SecureTransport": "false"&lt;br&gt;
        }&lt;br&gt;
      }&lt;br&gt;
    }&lt;br&gt;
  ]&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;To apply it: S3 → your bucket → Permissions → Bucket policy → Edit → paste → Save.&lt;/p&gt;

&lt;p&gt;Step 4: Restrict Access to a Specific IAM Role&lt;/p&gt;

&lt;p&gt;You can also lock the bucket so that only one role can access it. Replace the account ID and role name with your own:&lt;/p&gt;

&lt;p&gt;json&lt;br&gt;
{&lt;br&gt;
  "Version": "2012-10-17",&lt;br&gt;
  "Statement": [&lt;br&gt;
    {&lt;br&gt;
      "Sid": "AllowOnlyAppRole",&lt;br&gt;
      "Effect": "Allow",&lt;br&gt;
      "Principal": {&lt;br&gt;
        "AWS": "arn:aws:iam::123456789012:role/AppServerRole"&lt;br&gt;
      },&lt;br&gt;
      "Action": [&lt;br&gt;
        "s3:GetObject",&lt;br&gt;
        "s3:PutObject"&lt;br&gt;
      ],&lt;br&gt;
      "Resource": "arn:aws:s3:::vishal-secure-demo-bucket/*"&lt;br&gt;
    }&lt;br&gt;
  ]&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;This is useful when an EC2 instance or Lambda function needs access to the bucket. Use roles instead of long-term access keys.&lt;/p&gt;

&lt;p&gt;Step 5: Require Encryption on Upload&lt;/p&gt;

&lt;p&gt;This policy blocks any upload that isn't encrypted with SSE-KMS:&lt;/p&gt;

&lt;p&gt;json&lt;br&gt;
{&lt;br&gt;
  "Version": "2012-10-17",&lt;br&gt;
  "Statement": [&lt;br&gt;
    {&lt;br&gt;
      "Sid": "DenyUnencryptedUploads",&lt;br&gt;
      "Effect": "Deny",&lt;br&gt;
      "Principal": "&lt;em&gt;",&lt;br&gt;
      "Action": "s3:PutObject",&lt;br&gt;
      "Resource": "arn:aws:s3:::vishal-secure-demo-bucket/&lt;/em&gt;",&lt;br&gt;
      "Condition": {&lt;br&gt;
        "StringNotEquals": {&lt;br&gt;
          "s3:x-amz-server-side-encryption": "aws:kms"&lt;br&gt;
        }&lt;br&gt;
      }&lt;br&gt;
    }&lt;br&gt;
  ]&lt;br&gt;
}&lt;br&gt;
Step 6: Test Your Setup&lt;br&gt;
Try uploading a file with the IAM user: it should succeed.&lt;br&gt;
Try accessing the bucket over plain HTTP: it should be denied.&lt;br&gt;
Try accessing the bucket with a different user that has no permissions: you should see Access Denied.&lt;br&gt;
Use the IAM Policy Simulator or IAM Access Analyzer to validate your policies.&lt;br&gt;
S3 Security Best Practices&lt;br&gt;
Enable Block Public Access at both the bucket and account level.&lt;br&gt;
Follow least privilege. Grant only the actions and resources that are needed.&lt;br&gt;
Use IAM roles, not long-term access keys.&lt;br&gt;
Enforce HTTPS with aws:SecureTransport.&lt;br&gt;
Encrypt data at rest (SSE-S3 or SSE-KMS).&lt;br&gt;
Enable versioning and consider MFA Delete for critical data.&lt;br&gt;
Turn on logging with S3 server access logs and CloudTrail data events.&lt;br&gt;
Use IAM Access Analyzer to find buckets shared outside your account.&lt;br&gt;
Avoid "Principal": "&lt;em&gt;" with Allow unless you really mean public access.&lt;br&gt;
Review policies regularly and remove permissions that are no longer used.&lt;br&gt;
Common Mistakes to Avoid&lt;br&gt;
Using "Action": "s3:&lt;/em&gt;" and "Resource": "&lt;em&gt;" in IAM policies.&lt;br&gt;
Forgetting the /&lt;/em&gt; on the resource ARN for object-level actions.&lt;br&gt;
Making a bucket public "temporarily" and forgetting about it.&lt;br&gt;
Hardcoding access keys in application code.&lt;br&gt;
Not testing policies before applying them in production.&lt;br&gt;
Conclusion&lt;/p&gt;

&lt;p&gt;Securing S3 isn't about picking IAM policies or bucket policies. The strongest setups use both:&lt;/p&gt;

&lt;p&gt;IAM policies control what your users and roles can do.&lt;br&gt;
Bucket policies enforce rules at the bucket itself, like HTTPS-only access, encryption, and cross-account permissions.&lt;br&gt;
Block Public Access, encryption, and logging add extra layers of protection.&lt;/p&gt;

&lt;p&gt;Start with least privilege, test your policies, and review them regularly. Your data will be much safer for it.&lt;/p&gt;

&lt;p&gt;I'm learning and sharing my AWS journey step by step. If this article helped you, leave a comment or a reaction. Let me know which AWS topic you'd like me to cover next!&lt;/p&gt;

&lt;p&gt;Connect with me:&lt;/p&gt;

&lt;p&gt;LinkedIn: vishalpatil-devops-aws&lt;br&gt;
dev.to: &lt;a class="mentioned-user" href="https://dev.to/vishal_patil_aws"&gt;@vishal_patil_aws&lt;/a&gt;&lt;br&gt;
GitHub: VishalPatil-DevOps-AWS&lt;/p&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney #aws #s3 #security
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>infrastructure</category>
      <category>security</category>
    </item>
    <item>
      <title>Learning AWS as a Beginner: A Practical Roadmap with Hands-On Projects</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Sat, 31 Oct 2026 06:20:07 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/my-aws-learning-path-as-a-beginner-services-to-learn-and-projects-to-build-47nm</link>
      <guid>https://dev.to/vishal_patil_aws/my-aws-learning-path-as-a-beginner-services-to-learn-and-projects-to-build-47nm</guid>
      <description>&lt;p&gt;Learning AWS as a Beginner: A Practical Roadmap with Hands-On Projects&lt;/p&gt;

&lt;p&gt;When I started learning AWS, the biggest problem wasn't a lack of resources. It was knowing &lt;strong&gt;where to begin&lt;/strong&gt;. There are 200+ services, and most tutorials make it feel like you need to learn all of them.&lt;/p&gt;

&lt;p&gt;You don't. This article covers the order I'd recommend, the services that matter first, and the projects that actually make the concepts stick.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start with the Fundamentals
&lt;/h2&gt;

&lt;p&gt;Before touching services, understand the basics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Regions and Availability Zones&lt;/strong&gt;: where your resources physically live&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared Responsibility Model&lt;/strong&gt;: what AWS secures vs. what you secure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pay-as-you-go pricing&lt;/strong&gt;: why cost awareness matters from day one&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good way to validate this knowledge is the &lt;strong&gt;AWS Cloud Practitioner&lt;/strong&gt; path. I used &lt;strong&gt;AWS Cloud Quest: Cloud Practitioner&lt;/strong&gt;, a game-style, hands-on learning experience that earns you a badge.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Secure Your Account First
&lt;/h2&gt;

&lt;p&gt;Do this before building anything:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create your AWS account&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;MFA&lt;/strong&gt; on the root user&lt;/li&gt;
&lt;li&gt;Stop using root for daily work. Create an &lt;strong&gt;IAM user or role&lt;/strong&gt; instead&lt;/li&gt;
&lt;li&gt;Learn the difference between &lt;strong&gt;IAM Users, Groups, Roles, and Policies&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key idea: &lt;strong&gt;use roles for services and temporary access, and follow least privilege.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Set Up Billing Alarms and Budgets
&lt;/h2&gt;

&lt;p&gt;Surprise bills are the #1 beginner fear. Set up &lt;strong&gt;AWS Budgets&lt;/strong&gt; and a &lt;strong&gt;CloudWatch billing alarm&lt;/strong&gt; early so you get notified when spend crosses a threshold.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Free Tier terms have changed over time, so check the current AWS Free Tier page for what applies to your new account.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  4. Learn the Core Services in This Order
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Order&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;What it teaches you&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;IAM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Identity and access control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;EC2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Virtual servers, security groups, key pairs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;S3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Object storage, static website hosting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;VPC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Networking, subnets, routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CloudWatch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Monitoring, logs, alarms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;SNS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Notifications and alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;RDS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed databases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Lambda&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Serverless compute&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Don't try to master each one. Learn enough to build something small with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Practical Projects for Beginners
&lt;/h2&gt;

&lt;p&gt;Projects are where learning becomes real. Here are some that fit each stage:&lt;/p&gt;

&lt;h3&gt;
  
  
  Project 1: Launch and Connect to an EC2 Instance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Launch a free-tier-eligible instance&lt;/li&gt;
&lt;li&gt;Configure a security group&lt;/li&gt;
&lt;li&gt;SSH in and install a web server like NGINX&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills:&lt;/strong&gt; EC2, security groups, Linux basics&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project 2: Host a Static Website on S3
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a bucket, upload HTML/CSS/JS&lt;/li&gt;
&lt;li&gt;Enable static website hosting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills:&lt;/strong&gt; S3, bucket policies, permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project 3: EC2 Monitoring with CloudWatch + SNS Alerts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a CloudWatch alarm on EC2 CPU utilization&lt;/li&gt;
&lt;li&gt;Connect it to an SNS topic that emails you&lt;/li&gt;
&lt;li&gt;Trigger the alarm and watch it work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills:&lt;/strong&gt; CloudWatch, SNS, monitoring workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project 4: IAM Roles in Action
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create an IAM role with limited permissions&lt;/li&gt;
&lt;li&gt;Attach it to an EC2 instance so it can access S3 without hardcoded keys&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills:&lt;/strong&gt; IAM roles, least privilege, secure access patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project 5: Build a Simple VPC
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a custom VPC with public and private subnets&lt;/li&gt;
&lt;li&gt;Add an Internet Gateway and route tables&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills:&lt;/strong&gt; Networking fundamentals&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project 6: CI/CD with Jenkins on EC2 (Stretch Goal)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Run Jenkins on EC2 and connect it to GitHub&lt;/li&gt;
&lt;li&gt;Build and push a Docker image to Docker Hub&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills:&lt;/strong&gt; DevOps workflows, containers, automation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Habits That Make Learning Stick
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Build, then document.&lt;/strong&gt; Writing about what you built exposes gaps in your understanding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always clean up.&lt;/strong&gt; Terminate instances, delete buckets, and remove unused resources after each project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Break things on purpose.&lt;/strong&gt; Misconfigure a security group and see what fails. You learn faster from errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the console first, then automate.&lt;/strong&gt; Understand it manually before moving to CLI or Infrastructure as Code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share your progress.&lt;/strong&gt; Posting your learning publicly keeps you accountable and connects you with the community.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. What to Learn Next
&lt;/h2&gt;

&lt;p&gt;Once you're comfortable with the basics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS CLI and scripting&lt;/li&gt;
&lt;li&gt;Infrastructure as Code (CloudFormation or Terraform)&lt;/li&gt;
&lt;li&gt;Load balancers and Auto Scaling&lt;/li&gt;
&lt;li&gt;Containers (ECS/EKS)&lt;/li&gt;
&lt;li&gt;An associate-level certification such as Solutions Architect or SysOps&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;You don't need to know everything to start. Pick one service, build one small project, document it, and repeat. Consistency beats intensity.&lt;/p&gt;

&lt;p&gt;If you're on a similar journey, I'd love to hear which AWS project you're building next. Drop it in the comments!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Connect with me:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;Vishal Patil&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;VishalPatil-DevOps-AWS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;dev.to: &lt;a href="https://dev.to/vishal_patil_aws"&gt;@vishal_patil_aws&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>Why Building Your Career with AWS Is a Smart Move</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Fri, 30 Oct 2026 05:14:10 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/why-building-your-career-with-aws-is-a-smart-move-22bm</link>
      <guid>https://dev.to/vishal_patil_aws/why-building-your-career-with-aws-is-a-smart-move-22bm</guid>
      <description>&lt;p&gt;Key advantages of starting your cloud career with AWS: demand, learning paths, certifications, community, and growth.&lt;br&gt;
tags: aws, cloud, career, beginners&lt;/p&gt;




&lt;p&gt;Cloud computing is now the foundation of modern technology, and AWS sits at the center of it. Whether you are a student, a fresher, or a working professional switching tracks, building your career around AWS opens doors that few other skill sets can match. Here are the main advantages.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. High Demand Across Industries
&lt;/h2&gt;

&lt;p&gt;Startups, banks, healthcare companies, media platforms, and government bodies all run workloads on AWS. That means AWS skills are not tied to one sector. Roles such as Cloud Engineer, DevOps Engineer, Solutions Architect, Security Engineer, and Data Engineer all list AWS experience as a core requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Beginner-Friendly Learning Path
&lt;/h2&gt;

&lt;p&gt;AWS makes it easy to start from zero:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS Free Tier&lt;/strong&gt; lets you practice with real services without large costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Skill Builder&lt;/strong&gt; and &lt;strong&gt;AWS Cloud Quest&lt;/strong&gt; teach through guided, game-style labs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foundational certifications&lt;/strong&gt; like Cloud Practitioner give you a structured first milestone before moving to Associate and Professional levels.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You do not need a deep background to begin. You need curiosity and consistent hands-on practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Hands-On Skills That Employers Value
&lt;/h2&gt;

&lt;p&gt;AWS rewards learning by doing. Launching an EC2 instance, configuring IAM roles, setting up a VPC, or building CloudWatch alarms with SNS notifications teaches you real operational skills. These small projects become portfolio pieces that show employers you can build, not just memorize.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Industry-Recognized Certifications
&lt;/h2&gt;

&lt;p&gt;AWS certifications are among the most respected in the industry. They validate your knowledge, strengthen your resume, and give you a clear roadmap from Foundational to Associate, Professional, and Specialty levels. Digital badges through Credly make your achievements easy to share and verify on LinkedIn.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. A Broad Range of Career Paths
&lt;/h2&gt;

&lt;p&gt;Once you learn the AWS fundamentals, you can specialize in many directions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevOps and CI/CD&lt;/strong&gt;: automation, pipelines, containers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Architecture&lt;/strong&gt;: designing scalable, secure systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: IAM, encryption, compliance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data and AI/ML&lt;/strong&gt;: analytics, machine learning, generative AI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking and Infrastructure&lt;/strong&gt;: VPC, load balancing, hybrid setups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can start broad and narrow down as you discover what you enjoy.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Strong Community Support
&lt;/h2&gt;

&lt;p&gt;The AWS community is one of its biggest strengths. Programs like &lt;strong&gt;AWS Community Builders&lt;/strong&gt;, user groups, meetups, and &lt;strong&gt;AWS Builder Center&lt;/strong&gt; let you learn from others, share your own work, and build visibility. Writing articles, posting projects, and helping others is one of the fastest ways to grow your reputation as a cloud professional.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Better Earning and Growth Potential
&lt;/h2&gt;

&lt;p&gt;Cloud skills are in short supply compared to demand, so professionals with AWS expertise often see faster career progression and stronger salary prospects. As you combine AWS knowledge with skills like Linux, Docker, Terraform, and CI/CD, your value increases further.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Future-Proof Skills
&lt;/h2&gt;

&lt;p&gt;AWS continues to expand into serverless computing, containers, and AI and machine learning services such as Amazon Bedrock. Learning AWS today prepares you for how software will be built and run in the years ahead.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Get Started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create an AWS Free Tier account and set up billing alerts first.&lt;/li&gt;
&lt;li&gt;Learn core services: IAM, EC2, S3, VPC, and CloudWatch.&lt;/li&gt;
&lt;li&gt;Build small projects and document them publicly.&lt;/li&gt;
&lt;li&gt;Earn a foundational certification, then move to Associate level.&lt;/li&gt;
&lt;li&gt;Share what you learn through articles and community platforms.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building your career with AWS is not just about learning a platform. It is about developing practical, in-demand skills, joining a global community, and gaining the confidence to build real solutions. Start small, stay consistent, and document your journey as you go.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Vishal Patil&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; | 💻 &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; | ✍️ &lt;a href="https://dev.to/vishal_patil_aws"&gt;dev.to&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>career</category>
      <category>cloud</category>
    </item>
    <item>
      <title>13 AWS Badges in 2 Months: How I Started My Cloud Journey</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Thu, 29 Oct 2026 08:24:30 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/13-aws-badges-in-2-months-how-i-started-my-cloud-journey-1ld2</link>
      <guid>https://dev.to/vishal_patil_aws/13-aws-badges-in-2-months-how-i-started-my-cloud-journey-1ld2</guid>
      <description>&lt;p&gt;The order I earned 13 AWS and Linux Foundation badges between June and August 2026, what each one covers, and lessons for beginners."&lt;br&gt;
tags: aws, beginners, cloud, learning&lt;/p&gt;




&lt;p&gt;Two months ago I had no cloud credentials at all. Today my profile shows &lt;strong&gt;13 digital badges&lt;/strong&gt; earned between &lt;strong&gt;June 19 and August 18, 2026&lt;/strong&gt;. None of them is a certification, and I don't pretend they are. But together they gave me structure, vocabulary, and hands-on confidence.&lt;/p&gt;

&lt;p&gt;In this post I'll share the badges, the order I earned them in, and the lessons I'd pass on to anyone starting from zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  My 13 badges at a glance
&lt;/h2&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;Badge&lt;/th&gt;
&lt;th&gt;Issued by&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;AWS Educate: Introduction to Cloud 101&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Jun 19, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;AWS Educate: Getting Started with Compute&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Jun 30, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;AWS Educate: Getting Started with Storage&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Jul 3, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;AWS Educate: Getting Started with Networking&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Jul 25, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;AWS Educate: Getting Started with Databases&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Aug 1, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;AWS Educate: Getting Started with Cloud Ops&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Aug 2, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;AWS Educate: Getting Started with Serverless&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Aug 3, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;AWS Cloud Quest: Cloud Practitioner&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Aug 14, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;AWS Knowledge: AWS End User Computing&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Aug 17, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;AWS Knowledge: Cloud Essentials&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Aug 17, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;AWS Knowledge: Networking Core&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Aug 17, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;LFD103: A Beginner's Guide to Linux Kernel Development&lt;/td&gt;
&lt;td&gt;The Linux Foundation&lt;/td&gt;
&lt;td&gt;Aug 17, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;Well-Architected Proficient&lt;/td&gt;
&lt;td&gt;AWS Training and Certification&lt;/td&gt;
&lt;td&gt;Aug 18, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Phase 1: Building the foundation (June to July)
&lt;/h2&gt;

&lt;p&gt;I began with &lt;strong&gt;Introduction to Cloud 101&lt;/strong&gt; from AWS Educate. Before touching any service, I needed to understand what "the cloud" actually means: on-demand resources, pay-as-you-go pricing, and the global infrastructure.&lt;/p&gt;

&lt;p&gt;Then I worked through the &lt;strong&gt;Getting Started&lt;/strong&gt; series one service area at a time, starting with &lt;strong&gt;Compute&lt;/strong&gt; and &lt;strong&gt;Storage&lt;/strong&gt;. One topic per course kept things manageable. Instead of trying to learn "AWS" all at once, I learned what EC2 does, then what S3 does, then how they connect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 2: Going deeper into the core services (July to August)
&lt;/h2&gt;

&lt;p&gt;The next badges covered &lt;strong&gt;Networking&lt;/strong&gt;, &lt;strong&gt;Databases&lt;/strong&gt;, &lt;strong&gt;Cloud Ops&lt;/strong&gt;, and &lt;strong&gt;Serverless&lt;/strong&gt;. I earned the last three within three days, because the earlier courses had already built the vocabulary: VPCs, subnets, managed databases, monitoring, and Lambda stopped sounding like jargon.&lt;/p&gt;

&lt;p&gt;The most useful habit of this phase was trying the idea myself in the AWS Free Tier after each course. Reading about a security group and creating one are two very different experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 3: Learning by doing with Cloud Quest
&lt;/h2&gt;

&lt;p&gt;On August 14 I earned the &lt;strong&gt;AWS Cloud Quest: Cloud Practitioner&lt;/strong&gt; badge. Cloud Quest is a game-style, role-based experience where you build solutions in a virtual city. It was the point where theory turned into practice, because I had to apply ideas instead of just recognizing them in a quiz.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 4: The knowledge badges sprint
&lt;/h2&gt;

&lt;p&gt;On August 17 I earned three &lt;strong&gt;AWS Knowledge&lt;/strong&gt; badges: &lt;strong&gt;Cloud Essentials&lt;/strong&gt;, &lt;strong&gt;Networking Core&lt;/strong&gt;, and &lt;strong&gt;AWS End User Computing&lt;/strong&gt;. I also finished &lt;strong&gt;LFD103: A Beginner's Guide to Linux Kernel Development&lt;/strong&gt; from the Linux Foundation that day.&lt;/p&gt;

&lt;p&gt;That was a concentrated study day, not a typical one. The takeaway isn't "do four things in one day." It's that once the foundations are in place, later topics go much faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 5: Thinking like an architect
&lt;/h2&gt;

&lt;p&gt;The last badge, &lt;strong&gt;Well-Architected Proficient&lt;/strong&gt; (August 18), introduced me to the AWS Well-Architected Framework. It shifted my mindset from "how do I use this service?" to "is this design secure, reliable, efficient, and cost-aware?" I'd recommend taking it after you've seen the core services, not before.&lt;/p&gt;

&lt;h2&gt;
  
  
  What these badges are, and what they aren't
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;They are&lt;/strong&gt; proof that I completed structured training and met the requirements of each course&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;They are&lt;/strong&gt; shareable and verifiable, so anyone can check them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;They are not&lt;/strong&gt; AWS certifications, and they don't replace exams like Cloud Practitioner (CLF-C02)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I treat them as milestones on the way to certification, not the destination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons for beginners
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pick a clear order.&lt;/strong&gt; Cloud basics, then individual services, then hands-on practice, then architecture thinking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One topic at a time.&lt;/strong&gt; Small, focused courses are easier to finish and remember&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practice in your own account.&lt;/strong&gt; Do something in the Free Tier after every course, and set a billing alarm first&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Take notes in your own words&lt;/strong&gt;, then turn them into posts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mix sources.&lt;/strong&gt; The Linux Foundation course reminded me that cloud skills sit on top of operating system fundamentals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be consistent.&lt;/strong&gt; Two months of steady effort beat one burst of motivation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share your progress.&lt;/strong&gt; Writing publicly keeps you accountable and helps you understand topics better&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prepare for the &lt;strong&gt;AWS Certified Cloud Practitioner&lt;/strong&gt; exam&lt;/li&gt;
&lt;li&gt;Keep building hands-on projects (containers, monitoring, billing alerts) and writing about them&lt;/li&gt;
&lt;li&gt;Keep sharing what I learn here, on AWS Builder Center, and on LinkedIn&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Thirteen badges in two months didn't make me an expert. They gave me a map, and the habit of learning in public that I plan to keep. If you're starting out, pick your first course today.&lt;/p&gt;

&lt;p&gt;What was your first AWS badge, and what are you working on next? Let me know in the comments.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Connect with me&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;vishalpatil-devops-aws&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;dev.to: &lt;a href="https://dev.to/vishal_patil_aws"&gt;@vishal_patil_aws&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;VishalPatil-DevOps-AWS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Credly (Cloud Quest badge): &lt;a href="https://www.credly.com/badges/a615d775-05e1-4358-ae34-dc4f70a0a485/public_url" rel="noopener noreferrer"&gt;view badge&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney
&lt;/h1&gt;

</description>
      <category>learning</category>
      <category>beginners</category>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>AWS Skill Builder: The Free Official Platform to Start Your Cloud Journey</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Mon, 26 Oct 2026 23:48:19 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/aws-skill-builder-the-free-official-platform-to-start-your-cloud-journey-2pdm</link>
      <guid>https://dev.to/vishal_patil_aws/aws-skill-builder-the-free-official-platform-to-start-your-cloud-journey-2pdm</guid>
      <description>&lt;p&gt;When I started learning cloud, the hardest part wasn't the technology. It was knowing where to begin. There are endless YouTube playlists, paid courses, and blog posts, and it's easy to burn weeks just choosing what to study.&lt;/p&gt;

&lt;p&gt;The best answer I found is also the official one: &lt;strong&gt;AWS Skill Builder&lt;/strong&gt;. In this post I'll cover what it is, what you get for free, what the paid plans add, and how I'd use it as a beginner.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AWS Skill Builder?
&lt;/h2&gt;

&lt;p&gt;AWS Skill Builder is Amazon's official online learning platform. It offers on-demand courses, learning plans organized by role and certification, exam preparation, digital badges, and hands-on practice. The content is written and maintained by AWS, so it tracks the real services and the real exams.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get for free
&lt;/h2&gt;

&lt;p&gt;The free tier includes 600+ self-paced digital courses, learning plans, basic exam prep content, and digital badges. You don't need a credit card to start.&lt;/p&gt;

&lt;p&gt;Highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Digital courses&lt;/strong&gt; from beginner to advanced: compute, storage, networking, security, databases, and more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning plans&lt;/strong&gt; that group courses into a path so you don't have to guess the order&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Cloud Quest: Cloud Practitioner&lt;/strong&gt;, a game-style way to learn by building solutions in a virtual city&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic exam prep&lt;/strong&gt; content and practice questions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Digital badges&lt;/strong&gt; you can share on LinkedIn&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the paid plans add
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan&lt;/th&gt;
&lt;th&gt;Who it's for&lt;/th&gt;
&lt;th&gt;What it adds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Beginners&lt;/td&gt;
&lt;td&gt;Courses, learning plans, basic exam prep, badges&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Individual (from about $29/month)&lt;/td&gt;
&lt;td&gt;Learners preparing for certifications&lt;/td&gt;
&lt;td&gt;Builder Labs, full practice exams, AWS Jam challenge events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team&lt;/td&gt;
&lt;td&gt;Organizations&lt;/td&gt;
&lt;td&gt;Admin dashboards, reporting, SSO support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Do you need to pay? For most beginners, no. The free tier plus your own AWS Free Tier account covers a lot. A subscription makes sense when you're preparing for several certifications or want guided labs and full-length practice exams. If you try it, subscribe for one month, finish the labs you wanted, and cancel.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pricing and plan details change, so check the Skill Builder pricing page before deciding.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A beginner learning path
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with Cloud Practitioner Essentials.&lt;/strong&gt; It teaches the core AWS vocabulary: Regions, IAM, EC2, S3, pricing, and the shared responsibility model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Play AWS Cloud Quest: Cloud Practitioner.&lt;/strong&gt; It turns theory into practice, and finishing it earns a badge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the exam prep learning plan&lt;/strong&gt; if you're aiming for the Cloud Practitioner certification (CLF-C02).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practice in your own account.&lt;/strong&gt; Use the AWS Free Tier to repeat what you learned: create an IAM user, launch an EC2 instance, set up a billing alarm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move to an Associate-level path&lt;/strong&gt; such as Solutions Architect or Developer once the basics feel comfortable.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  My experience
&lt;/h2&gt;

&lt;p&gt;I earned the &lt;strong&gt;AWS Cloud Quest: Cloud Practitioner (Trained)&lt;/strong&gt; badge through Skill Builder, and it did more for my understanding than passive video watching. Building a solution inside the game, then recreating it in my own AWS account, made the concepts stick. You can see the badge on &lt;a href="https://www.credly.com/badges/a615d775-05e1-4358-ae34-dc4f70a0a485/public_url" rel="noopener noreferrer"&gt;Credly&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips to get the most out of it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Follow a learning plan&lt;/strong&gt; instead of picking random courses&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Take notes in your own words&lt;/strong&gt;, then turn them into blog posts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pair every course with a small hands-on task&lt;/strong&gt; in the Free Tier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set a billing alarm first&lt;/strong&gt; so practice never surprises you with a bill&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share your badges&lt;/strong&gt; on LinkedIn to document your progress&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be consistent.&lt;/strong&gt; Thirty focused minutes a day beats a six-hour weekend binge&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Free tier limits to know about
&lt;/h2&gt;

&lt;p&gt;The free tier is generous but not unlimited. Guided hands-on labs and full practice exams are mostly part of the paid plan, and free courses don't give you a completion certificate like an official certification does. Badges show learning progress. They don't replace a certification exam.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;If you're starting with AWS, Skill Builder is the best first stop: official, structured, and largely free. Pick a learning plan, practice in your own account, and share what you learn. That combination is what turns courses into real skills.&lt;/p&gt;

&lt;p&gt;What's your favorite Skill Builder course so far? Let me know in the comments.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Connect with me&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;vishalpatil-devops-aws&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;dev.to: &lt;a href="https://dev.to/vishal_patil_aws"&gt;@vishal_patil_aws&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;VishalPatil-DevOps-AWS&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>beginners</category>
      <category>cloud</category>
      <category>learning</category>
    </item>
    <item>
      <title>Deploy a Container on AWS with ECR and ECS (Fargate): Beginner's Guide</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Sun, 25 Oct 2026 06:10:34 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/deploy-a-container-on-aws-with-ecr-and-ecs-fargate-beginners-guide-jj</link>
      <guid>https://dev.to/vishal_patil_aws/deploy-a-container-on-aws-with-ecr-and-ecs-fargate-beginners-guide-jj</guid>
      <description>&lt;p&gt;Push a Docker image to Amazon ECR and run it on ECS with Fargate, step by step, with CLI commands and common errors."&lt;/p&gt;

&lt;h2&gt;
  
  
  tags: aws, docker, devops, containers
&lt;/h2&gt;

&lt;p&gt;Running a container on your laptop is easy. Running it reliably in the cloud means you need somewhere to store images and something to run, restart, and scale them. On AWS, that's &lt;strong&gt;Amazon ECR&lt;/strong&gt; and &lt;strong&gt;Amazon ECS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this post I'll explain what each does and walk through deploying a containerized app on &lt;strong&gt;Fargate&lt;/strong&gt;, so there are no servers to manage.&lt;/p&gt;

&lt;h2&gt;
  
  
  ECR vs ECS in one minute
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Amazon ECR (Elastic Container Registry)&lt;/strong&gt; is a private, managed registry for your container images. Think of it as a Docker Hub that lives inside your AWS account, with IAM-based access control, vulnerability scanning, and lifecycle policies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amazon ECS (Elastic Container Service)&lt;/strong&gt; is the orchestrator. You describe what to run, and ECS places it, restarts it if it fails, and keeps the desired number of copies running.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cluster&lt;/td&gt;
&lt;td&gt;Logical grouping of tasks and services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task definition&lt;/td&gt;
&lt;td&gt;Blueprint: image, CPU, memory, ports, env vars, roles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task&lt;/td&gt;
&lt;td&gt;A running instance of a task definition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service&lt;/td&gt;
&lt;td&gt;Keeps N tasks running and replaces failed ones&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fargate&lt;/td&gt;
&lt;td&gt;Serverless compute for containers, no EC2 to manage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build → docker push → ECR (stores image)
                                ↓
              ECS task definition points to the image URI
                                ↓
              ECS service runs tasks on Fargate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;An AWS account&lt;/li&gt;
&lt;li&gt;AWS CLI configured (&lt;code&gt;aws configure&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Docker installed&lt;/li&gt;
&lt;li&gt;A small app with a &lt;code&gt;Dockerfile&lt;/code&gt; (Nginx or Node.js is fine)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Create the ECR repository
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecr create-repository &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--repository-name&lt;/span&gt; my-app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the &lt;code&gt;repositoryUri&lt;/code&gt; from the output. It looks like &lt;code&gt;&amp;lt;account-id&amp;gt;.dkr.ecr.ap-south-1.amazonaws.com/my-app&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Build, tag, and push the image
&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;# Build&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-app &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Authenticate Docker to ECR&lt;/span&gt;
aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1 | &lt;span class="se"&gt;\&lt;/span&gt;
docker login &lt;span class="nt"&gt;--username&lt;/span&gt; AWS &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&amp;lt;account-id&amp;gt;.dkr.ecr.ap-south-1.amazonaws.com

&lt;span class="c"&gt;# Tag and push&lt;/span&gt;
docker tag my-app:latest &amp;lt;account-id&amp;gt;.dkr.ecr.ap-south-1.amazonaws.com/my-app:latest
docker push &amp;lt;account-id&amp;gt;.dkr.ecr.ap-south-1.amazonaws.com/my-app:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the ECR console and you should see the image with the &lt;code&gt;latest&lt;/code&gt; tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Create an ECS cluster
&lt;/h2&gt;

&lt;p&gt;In the ECS console, choose &lt;strong&gt;Clusters → Create cluster&lt;/strong&gt;, name it &lt;code&gt;my-app-cluster&lt;/code&gt;, keep &lt;strong&gt;AWS Fargate (serverless)&lt;/strong&gt; selected, and create it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Create the task definition
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Task definitions → Create new task definition&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;my-app-task&lt;/code&gt;, launch type: &lt;strong&gt;AWS Fargate&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Size: for example 0.5 vCPU / 1 GB for a small app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task execution role:&lt;/strong&gt; &lt;code&gt;ecsTaskExecutionRole&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add a container with your ECR image URI and container port (for example &lt;code&gt;80&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Leave CloudWatch logging enabled&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 5: Run it as a service
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the cluster → &lt;strong&gt;Services → Create&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Launch type: &lt;strong&gt;Fargate&lt;/strong&gt;, pick your task definition&lt;/li&gt;
&lt;li&gt;Desired tasks: &lt;code&gt;1&lt;/code&gt; (use &lt;code&gt;2&lt;/code&gt; for availability)&lt;/li&gt;
&lt;li&gt;Choose your VPC and subnets&lt;/li&gt;
&lt;li&gt;Use a security group that allows inbound traffic on the container port&lt;/li&gt;
&lt;li&gt;Create the service&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 6: Test it
&lt;/h2&gt;

&lt;p&gt;When the task shows &lt;strong&gt;RUNNING&lt;/strong&gt;, open it, copy the &lt;strong&gt;public IP&lt;/strong&gt;, and visit &lt;code&gt;http://&amp;lt;public-ip&amp;gt;&lt;/code&gt;. Your container is live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Task role vs task execution role
&lt;/h2&gt;

&lt;p&gt;This trips up a lot of beginners:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Task execution role:&lt;/strong&gt; used by ECS itself to pull the image from ECR and write logs to CloudWatch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task role:&lt;/strong&gt; used by your app code inside the container to call AWS services (for example, reading from S3)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep both as narrow as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CannotPullContainerError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Execution role missing permissions, wrong image URI, or no network path to ECR (needs a public IP or NAT/VPC endpoints)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task keeps stopping&lt;/td&gt;
&lt;td&gt;App crashes on startup. Check CloudWatch logs and the exit code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can't reach the app&lt;/td&gt;
&lt;td&gt;Security group doesn't allow the container port, or the task has no public IP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service stuck at 0 running tasks&lt;/td&gt;
&lt;td&gt;Check the service &lt;strong&gt;Events&lt;/strong&gt; tab for the exact error&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Don't deploy &lt;code&gt;latest&lt;/code&gt; to production. Tag images with a version or commit hash&lt;/li&gt;
&lt;li&gt;Turn on &lt;strong&gt;scan on push&lt;/strong&gt; in ECR&lt;/li&gt;
&lt;li&gt;Add &lt;strong&gt;lifecycle policies&lt;/strong&gt; to expire old untagged images&lt;/li&gt;
&lt;li&gt;Put an &lt;strong&gt;Application Load Balancer&lt;/strong&gt; in front and run tasks in private subnets for production&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;least-privilege IAM&lt;/strong&gt; roles&lt;/li&gt;
&lt;li&gt;Store secrets in &lt;strong&gt;Secrets Manager&lt;/strong&gt; or &lt;strong&gt;SSM Parameter Store&lt;/strong&gt;, never as plain text in the task definition&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;ECR gives your images a secure home, and ECS on Fargate runs them without any server management. Once images, task definitions, and services click, you have the foundation for production-ready container workloads on AWS. A good next step is adding an ALB and auto scaling, then automating the build-and-deploy flow with CI/CD.&lt;/p&gt;

&lt;p&gt;If you found this useful, let me know in the comments what you'd like me to cover next.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Connect with me&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;vishalpatil-devops-aws&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;dev.to: &lt;a href="https://dev.to/vishal_patil_aws"&gt;@vishal_patil_aws&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;VishalPatil-DevOps-AWS&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>beginners</category>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Set Up AWS Budgets and Billing Alarms: Never Get a Surprise AWS Bill</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Sat, 24 Oct 2026 06:41:51 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/set-up-aws-budgets-and-billing-alarms-never-get-a-surprise-aws-bill-26gk</link>
      <guid>https://dev.to/vishal_patil_aws/set-up-aws-budgets-and-billing-alarms-never-get-a-surprise-aws-bill-26gk</guid>
      <description>&lt;p&gt;A beginner-friendly guide to AWS Budgets, CloudWatch billing alarms and Free Tier alerts, so you never get a surprise AWS bill. &lt;/p&gt;




&lt;p&gt;Almost every AWS beginner has the same fear: leaving something running and getting a bill at the end of the month that they didn't expect. The good news is that AWS gives you free tools to catch this early.&lt;/p&gt;

&lt;p&gt;In this article, you'll set up two safety nets in about 15 minutes: an AWS Budget and a CloudWatch billing alarm, plus Free Tier usage alerts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you need alerts from day one
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A forgotten EC2 instance, NAT Gateway, load balancer or Elastic IP keeps costing money while you're not using it.&lt;/li&gt;
&lt;li&gt;Practice projects are easy to forget after the tutorial ends.&lt;/li&gt;
&lt;li&gt;Alerts tell you early, when the amount is still small and easy to fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  AWS Budgets vs CloudWatch billing alarms
&lt;/h2&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;AWS Budgets&lt;/th&gt;
&lt;th&gt;CloudWatch billing alarm&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What it tracks&lt;/td&gt;
&lt;td&gt;Cost or usage against a limit you set, including forecasted spend&lt;/td&gt;
&lt;td&gt;Total estimated charges so far this month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Where you set it&lt;/td&gt;
&lt;td&gt;Billing and Cost Management console&lt;/td&gt;
&lt;td&gt;CloudWatch console, in us-east-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Notification&lt;/td&gt;
&lt;td&gt;Email or SNS at thresholds you choose&lt;/td&gt;
&lt;td&gt;SNS topic (email, SMS, Lambda and more)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Monitoring and notifications are free&lt;/td&gt;
&lt;td&gt;Standard CloudWatch alarm pricing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Planning: "tell me before I exceed my limit"&lt;/td&gt;
&lt;td&gt;A simple tripwire: "tell me if charges pass $X"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use both. They are cheap, quick to set up, and cover each other's gaps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account and access to the root user, or an IAM user with billing permissions&lt;/li&gt;
&lt;li&gt;A working email address&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note for IAM users: By default only the root user can see billing pages. The root user must turn on IAM user and role access to Billing information in Account settings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Part 1: Turn on billing alerts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open Billing and Cost Management in the console.&lt;/li&gt;
&lt;li&gt;Go to Billing preferences.&lt;/li&gt;
&lt;li&gt;Under Alert preferences, enable AWS Free Tier alerts and add your email.&lt;/li&gt;
&lt;li&gt;Enable CloudWatch billing alerts (needed for Part 3) and save.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Menu labels change from time to time, so if something looks slightly different, search for "Billing preferences" in the Billing console.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Create a monthly cost budget
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open Budgets and choose Create budget.&lt;/li&gt;
&lt;li&gt;Pick the Monthly cost budget template. (The Zero spend budget alerts you as soon as spending goes above the Free Tier.)&lt;/li&gt;
&lt;li&gt;Name it (for example &lt;code&gt;monthly-cost-budget&lt;/code&gt;) and set an amount such as $5 or $10 for a learning account.&lt;/li&gt;
&lt;li&gt;Enter the email address(es) for alerts.&lt;/li&gt;
&lt;li&gt;Choose **Create budget.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then add thresholds:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Alert&lt;/th&gt;
&lt;th&gt;Threshold&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Actual cost&lt;/td&gt;
&lt;td&gt;50% of budget&lt;/td&gt;
&lt;td&gt;Early heads-up that you're spending faster than planned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Actual cost&lt;/td&gt;
&lt;td&gt;80% of budget&lt;/td&gt;
&lt;td&gt;Time to review what's running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Forecasted&lt;/strong&gt; cost&lt;/td&gt;
&lt;td&gt;100% of budget&lt;/td&gt;
&lt;td&gt;Warns you before you cross the limit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Good to know : AWS updates budget data a few times a day, so alerts aren't instant. Monitoring and notifications are free. Only optional extras cost money: after your first two action-enabled budgets each month, extra ones cost $0.10 per day, and each emailed Budgets report costs $0.01.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Part 3: Create a CloudWatch billing alarm
&lt;/h2&gt;

&lt;p&gt;Billing metrics are only published in US East (N. Virginia) us-east-1, so switch to that Region first, even if your resources are elsewhere.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open CloudWatch and switch the Region to US East (N. Virginia).&lt;/li&gt;
&lt;li&gt;Go to Alarms → All alarms → Create alarm → Select metric.&lt;/li&gt;
&lt;li&gt;Choose Billing → Total Estimated Charge**, select the USD metric (&lt;code&gt;EstimatedCharges&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Set Statistic = Maximum,Period = 6 hours, Static, Greater than your limit (for example &lt;code&gt;5&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Create a new SNS topic (for example &lt;code&gt;billing-alerts&lt;/code&gt;) and enter your email.&lt;/li&gt;
&lt;li&gt;Name the alarm (for example &lt;code&gt;Billing-Alarm-5-USD&lt;/code&gt;) and create it.&lt;/li&gt;
&lt;li&gt;Open your inbox and confirm the SNS subscription email. Until you do, no alerts will reach you.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Prefer the CLI? Use this (replace the SNS topic ARN with yours):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&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="s2"&gt;"Billing-Alarm-5-USD"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; &lt;span class="s2"&gt;"AWS/Billing"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metric-name&lt;/span&gt; &lt;span class="s2"&gt;"EstimatedCharges"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dimensions&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Currency,Value&lt;span class="o"&gt;=&lt;/span&gt;USD &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--statistic&lt;/span&gt; Maximum &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--period&lt;/span&gt; 21600 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--evaluation-periods&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--threshold&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--comparison-operator&lt;/span&gt; GreaterThanThreshold &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--alarm-actions&lt;/span&gt; arn:aws:sns:us-east-1:&amp;lt;account-id&amp;gt;:billing-alerts &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 4: Verify everything works
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;What to look for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Budgets console&lt;/td&gt;
&lt;td&gt;Your budget is listed with status "OK"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloudWatch (us-east-1)&lt;/td&gt;
&lt;td&gt;The alarm shows "OK" (or "Insufficient data" briefly)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SNS&lt;/td&gt;
&lt;td&gt;The subscription status is Confirmed, not "Pending"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email&lt;/td&gt;
&lt;td&gt;You received the Free Tier alert and SNS confirmation messages&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No billing metric in CloudWatch&lt;/td&gt;
&lt;td&gt;Switch to us-east-1 and enable CloudWatch billing alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alarm never sends email&lt;/td&gt;
&lt;td&gt;Confirm the SNS subscription email and check spam&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can't open billing pages as an IAM user&lt;/td&gt;
&lt;td&gt;Root user must activate IAM access to Billing information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alert arrived but charges are unclear&lt;/td&gt;
&lt;td&gt;Use **Cost Explorer and group by Service&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Alerts are notifications, not a spending cap. AWS won't stop your resources automatically, so act when you get the email.&lt;/li&gt;
&lt;li&gt;Use several thresholds (50%, 80%, forecasted 100%).&lt;/li&gt;
&lt;li&gt;Check Cost Explorer once a week while you're learning.&lt;/li&gt;
&lt;li&gt;Tag lab resources (for example &lt;code&gt;Project=learning&lt;/code&gt;) so they're easy to find and delete.&lt;/li&gt;
&lt;li&gt;Delete resources after every lab: EC2, NAT Gateways, load balancers, unused Elastic IPs and old EBS volumes.&lt;/li&gt;
&lt;li&gt;Protect the root user with MFA.&lt;/li&gt;
&lt;li&gt;Next step: explore &lt;strong&gt;AWS Budgets Actions&lt;/strong&gt; and Cost Anomaly Detection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Setting up AWS Budgets and billing alarms takes only a few minutes, costs nothing for the basic setup, and protects you from the most common beginner mistake in the cloud. Do it once, right after you create your account, and you can experiment with AWS services with much more confidence.&lt;/p&gt;

&lt;p&gt;If this helped you, let me know which AWS topic you'd like me to cover next.&lt;/p&gt;




&lt;p&gt;Author : Vishal Patil&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn: &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/vishalpatil-devops-aws/&lt;/a&gt;&lt;br&gt;
💻 GitHub: &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;https://github.com/VishalPatil-DevOps-AWS&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney #AWS #AWSBudgets #CloudWatch #CostOptimization #FinOps #DevOps
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>beginners</category>
      <category>infrastructure</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>From Dockerfile to the Cloud: Deploy a Docker Container on AWS with ECR and ECS Fargate"</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Fri, 23 Oct 2026 07:17:04 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/from-dockerfile-to-the-cloud-deploy-a-docker-container-on-aws-with-ecr-and-ecs-fargate-g73</link>
      <guid>https://dev.to/vishal_patil_aws/from-dockerfile-to-the-cloud-deploy-a-docker-container-on-aws-with-ecr-and-ecs-fargate-g73</guid>
      <description>&lt;p&gt;description: "A beginner-friendly, step-by-step guide to packaging an app with Docker, storing it in Amazon ECR, and running it on ECS Fargate with no servers to manage."&lt;br&gt;
tags: aws, docker, devops, vishalcloudjourney&lt;/p&gt;



&lt;p&gt;Docker is one of the most useful skills for anyone moving into cloud and DevOps. Running a container on your laptop is easy. The real question is how to run it reliably on AWS without managing servers.&lt;/p&gt;

&lt;p&gt;In this article, you'll take a simple app from a &lt;strong&gt;Dockerfile&lt;/strong&gt; to a &lt;strong&gt;running container on AWS&lt;/strong&gt;, using these services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt; to package the app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon ECR&lt;/strong&gt; (Elastic Container Registry) to store the image&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon ECS with AWS Fargate&lt;/strong&gt; to run the container with no EC2 instances to manage&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What You'll Need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account (a Free Tier account is fine for learning)&lt;/li&gt;
&lt;li&gt;Docker installed on your machine&lt;/li&gt;
&lt;li&gt;AWS CLI installed and configured (&lt;code&gt;aws configure&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Node.js (optional, only to test the app outside Docker)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1: Create a Simple App
&lt;/h2&gt;

&lt;p&gt;Create a folder called &lt;code&gt;my-docker-app&lt;/code&gt; with these files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;app.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello from Docker running on AWS Fargate!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.0.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;App running on port 3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;package.json&lt;/strong&gt;&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;"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;"my-docker-app"&lt;/span&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;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"app.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&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;"express"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.19.2"&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;h2&gt;
  
  
  Step 2: Write the Dockerfile
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:20-alpine&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "app.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it's written this way:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;alpine&lt;/code&gt; gives you a small image, so pulls are faster and the attack surface is smaller.&lt;/li&gt;
&lt;li&gt;Copying &lt;code&gt;package*.json&lt;/code&gt; first lets Docker cache the dependency layer, so rebuilds are much faster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Build and Test Locally
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-docker-app:v1 &lt;span class="nb"&gt;.&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 my-docker-app:v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:3000&lt;/code&gt;. You should see your message. Always test locally first, because it saves a lot of debugging time later.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If you're on an Apple Silicon Mac, build with &lt;code&gt;--platform linux/amd64&lt;/code&gt; so the image runs on standard Fargate.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4: Push the Image to Amazon ECR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Create the repository:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecr create-repository &lt;span class="nt"&gt;--repository-name&lt;/span&gt; my-docker-app &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Authenticate Docker to ECR&lt;/strong&gt; (replace &lt;code&gt;&amp;lt;account-id&amp;gt;&lt;/code&gt; with your 12-digit AWS account ID):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; ap-south-1 | docker login &lt;span class="nt"&gt;--username&lt;/span&gt; AWS &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; &amp;lt;account-id&amp;gt;.dkr.ecr.ap-south-1.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tag and push:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag my-docker-app:v1 &amp;lt;account-id&amp;gt;.dkr.ecr.ap-south-1.amazonaws.com/my-docker-app:v1
docker push &amp;lt;account-id&amp;gt;.dkr.ecr.ap-south-1.amazonaws.com/my-docker-app:v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go to &lt;strong&gt;ECR → Repositories → my-docker-app&lt;/strong&gt; in the console. Your image should now be listed.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Amazon ECS → Clusters → Create cluster&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name it &lt;code&gt;docker-demo-cluster&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Under infrastructure, keep &lt;strong&gt;AWS Fargate (serverless)&lt;/strong&gt; selected&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;A task definition is the blueprint for your container.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;ECS → Task definitions → Create new task definition&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;my-docker-app-task&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Launch type: &lt;strong&gt;AWS Fargate&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;CPU / Memory: &lt;strong&gt;0.25 vCPU / 0.5 GB&lt;/strong&gt; (enough for this demo)&lt;/li&gt;
&lt;li&gt;Task execution role: &lt;code&gt;ecsTaskExecutionRole&lt;/code&gt; (let ECS create it if it doesn't exist)&lt;/li&gt;
&lt;li&gt;Container details:

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;my-docker-app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Image URI: &lt;code&gt;&amp;lt;account-id&amp;gt;.dkr.ecr.ap-south-1.amazonaws.com/my-docker-app:v1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Container port: &lt;code&gt;3000&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The execution role is what allows Fargate to pull your image from ECR and send logs to CloudWatch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Run the Container as a Service
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open your cluster and go to &lt;strong&gt;Services → Create&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Compute option: &lt;strong&gt;Launch type → Fargate&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Task definition: &lt;code&gt;my-docker-app-task&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Desired tasks: &lt;code&gt;1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Networking&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Pick your VPC and a public subnet&lt;/li&gt;
&lt;li&gt;Create or select a &lt;strong&gt;security group&lt;/strong&gt; that allows &lt;strong&gt;inbound TCP 3000&lt;/strong&gt; from your IP (or &lt;code&gt;0.0.0.0/0&lt;/code&gt; for a quick demo only)&lt;/li&gt;
&lt;li&gt;Turn &lt;strong&gt;Public IP&lt;/strong&gt; on&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Wait a minute or two until the task status shows &lt;strong&gt;Running&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Test It
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Cluster → Tasks → select your running task&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Copy the &lt;strong&gt;Public IP&lt;/strong&gt; from the networking section&lt;/li&gt;
&lt;li&gt;Visit &lt;code&gt;http://&amp;lt;public-ip&amp;gt;:3000&lt;/code&gt; in your browser&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You'll see: &lt;strong&gt;Hello from Docker running on AWS Fargate!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your container is now running on AWS with no servers to patch or manage.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Likely Cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Task stops immediately&lt;/td&gt;
&lt;td&gt;Check the container logs in CloudWatch and confirm the &lt;code&gt;CMD&lt;/code&gt; is correct&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can't pull the image&lt;/td&gt;
&lt;td&gt;The execution role is missing ECR permissions, or the image URI has a typo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page doesn't load&lt;/td&gt;
&lt;td&gt;Security group isn't allowing port 3000, or the public IP isn't enabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"exec format error"&lt;/td&gt;
&lt;td&gt;Image built for the wrong CPU architecture (see the platform tip in Step 3)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don't use the &lt;code&gt;latest&lt;/code&gt; tag in production.&lt;/strong&gt; Use versioned tags like &lt;code&gt;v1&lt;/code&gt; and &lt;code&gt;v2&lt;/code&gt; so you can roll back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn on ECR image scanning&lt;/strong&gt; to catch known vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use least-privilege IAM roles&lt;/strong&gt; for tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put an Application Load Balancer in front&lt;/strong&gt; for real workloads instead of exposing the task's public IP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send logs to CloudWatch&lt;/strong&gt; and set alarms on failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Clean Up to Avoid Charges
&lt;/h2&gt;

&lt;p&gt;When you're done:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set the ECS service desired count to &lt;code&gt;0&lt;/code&gt;, then delete the service&lt;/li&gt;
&lt;li&gt;Delete the cluster&lt;/li&gt;
&lt;li&gt;Delete the ECR repository (or the image)&lt;/li&gt;
&lt;li&gt;Delete any security groups you created for the demo&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You've taken an application from source code to a running container on AWS using Docker, ECR, and ECS Fargate. This same pattern scales from a small demo to production workloads. Adding an ALB, auto scaling, and a CI/CD pipeline are natural next steps.&lt;/p&gt;

&lt;p&gt;If you found this helpful, let me know which topic you'd like me to cover next.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Vishal Patil&lt;/p&gt;

&lt;p&gt;🔗 LinkedIn: &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;vishalpatil-devops-aws&lt;/a&gt;&lt;br&gt;
💻 GitHub: &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;VishalPatil-DevOps-AWS&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney #AWS #Docker #ECS #Fargate #ECR #DevOps #Containers
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>AWS RDS Explained: Launch, Secure, and Scale a Managed Database</title>
      <dc:creator>Vishal Patil</dc:creator>
      <pubDate>Thu, 22 Oct 2026 02:38:51 +0000</pubDate>
      <link>https://dev.to/vishal_patil_aws/aws-rds-explained-launch-secure-and-scale-a-managed-database-6g6</link>
      <guid>https://dev.to/vishal_patil_aws/aws-rds-explained-launch-secure-and-scale-a-managed-database-6g6</guid>
      <description>

&lt;p&gt;&lt;em&gt;By Vishal Patil | #vishalcloudjourney&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Running a database on your own EC2 instance means you are also the DBA. You patch the OS, schedule backups, set up replication, and wake up when the disk fills. &lt;strong&gt;Amazon RDS (Relational Database Service)&lt;/strong&gt; takes that operational work off your plate so you can focus on your application. In this hands-on guide, you'll launch a MySQL database on RDS, lock it down, connect from EC2, test automatic failover, and learn how to scale reads.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Amazon RDS?
&lt;/h2&gt;

&lt;p&gt;Amazon RDS is a managed service for relational databases. You choose the engine and size, and AWS handles the heavy lifting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supported engines:&lt;/strong&gt; Amazon Aurora (MySQL and PostgreSQL compatible), MySQL, PostgreSQL, MariaDB, Oracle, SQL Server, and Db2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AWS manages for you&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hardware provisioning and OS patching&lt;/li&gt;
&lt;li&gt;Automated backups and point-in-time recovery&lt;/li&gt;
&lt;li&gt;Database software patching during a maintenance window&lt;/li&gt;
&lt;li&gt;Multi-AZ failover&lt;/li&gt;
&lt;li&gt;Monitoring through CloudWatch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What you still manage&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schema design, queries, and indexes&lt;/li&gt;
&lt;li&gt;Security groups, network placement, and user access&lt;/li&gt;
&lt;li&gt;Choosing instance size and storage&lt;/li&gt;
&lt;li&gt;Cost control&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; With standard RDS you don't get SSH or OS-level access to the underlying host. That's the trade-off for a managed service.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What You Will Build
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A security group setup where &lt;strong&gt;only your EC2 app server&lt;/strong&gt; can reach the database&lt;/li&gt;
&lt;li&gt;A private MySQL RDS instance with encryption and automated backups&lt;/li&gt;
&lt;li&gt;A connection from EC2 to the database&lt;/li&gt;
&lt;li&gt;A Multi-AZ standby and a failover test&lt;/li&gt;
&lt;li&gt;(Optional) A read replica&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Architecture:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EC2 app server (ec2-app-sg) → RDS MySQL primary (rds-sg, AZ-a)
                                  ↓ synchronous replication
                              RDS standby (AZ-b), takes over on failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Concepts in 60 Seconds
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DB instance:&lt;/strong&gt; The managed database server you pay for.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DB subnet group:&lt;/strong&gt; The subnets (in at least two AZs) where RDS is allowed to place your database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-AZ:&lt;/strong&gt; A standby copy in another AZ, kept in sync, that takes over automatically if the primary fails. It's for &lt;strong&gt;availability&lt;/strong&gt;, not for read scaling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read replica:&lt;/strong&gt; An asynchronously updated copy used to &lt;strong&gt;scale read traffic&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated backups:&lt;/strong&gt; Daily backups plus transaction logs, kept for 1 to 35 days, enabling point-in-time restore.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snapshot:&lt;/strong&gt; A manual backup that stays until you delete it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Endpoint:&lt;/strong&gt; The DNS name your application uses to connect. Always use the endpoint, never an IP.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;An AWS account with permissions for RDS, EC2, and VPC&lt;/li&gt;
&lt;li&gt;A VPC with subnets in at least two AZs (the default VPC works)&lt;/li&gt;
&lt;li&gt;A running EC2 instance (Amazon Linux 2023) to act as your app server, or you can launch one in Step 4&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Cost note:&lt;/strong&gt; RDS bills while the instance is running, and Multi-AZ roughly doubles the instance cost. Check the current Free Tier terms for your account and follow the cleanup section at the end.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 1: Create the Security Groups
&lt;/h2&gt;

&lt;p&gt;Use two security groups so the database is reachable only from your app server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App security group (&lt;code&gt;ec2-app-sg&lt;/code&gt;)&lt;/strong&gt; attached to your EC2 instance&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inbound: SSH (22) from your IP, or use EC2 Instance Connect or Session Manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Database security group (&lt;code&gt;rds-sg&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inbound: &lt;strong&gt;MySQL/Aurora (3306)&lt;/strong&gt; from &lt;strong&gt;&lt;code&gt;ec2-app-sg&lt;/code&gt;&lt;/strong&gt; (select the security group as the source, not &lt;code&gt;0.0.0.0/0&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the single most important RDS security habit: never open your database port to the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Check the DB Subnet Group
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;RDS → Subnet groups&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The default VPC already has a &lt;code&gt;default&lt;/code&gt; subnet group covering its subnets.&lt;/li&gt;
&lt;li&gt;For your own VPC, create a subnet group and add subnets from &lt;strong&gt;at least two AZs&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 3: Create the Database
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;RDS → Databases → Create database&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Standard create&lt;/strong&gt; and engine &lt;strong&gt;MySQL&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Template: &lt;strong&gt;Free tier&lt;/strong&gt; or &lt;strong&gt;Dev/Test&lt;/strong&gt;, depending on what your account shows.&lt;/li&gt;
&lt;li&gt;Settings:

&lt;ul&gt;
&lt;li&gt;DB instance identifier: &lt;code&gt;mydb-rds&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Master username: &lt;code&gt;admin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Credentials: choose &lt;strong&gt;Managed in AWS Secrets Manager&lt;/strong&gt; (recommended), or set a strong password yourself&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Instance configuration: a small burstable class such as &lt;code&gt;db.t4g.micro&lt;/code&gt; or &lt;code&gt;db.t3.micro&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Storage:

&lt;ul&gt;
&lt;li&gt;Type: &lt;strong&gt;General Purpose SSD (gp3)&lt;/strong&gt;, 20 GiB&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;storage autoscaling&lt;/strong&gt; with a sensible maximum&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Connectivity:

&lt;ul&gt;
&lt;li&gt;VPC and subnet group: your chosen ones&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Public access: No&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;VPC security group: &lt;code&gt;rds-sg&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Additional configuration:

&lt;ul&gt;
&lt;li&gt;Initial database name: &lt;code&gt;appdb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated backups:&lt;/strong&gt; enabled, retention 7 days&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encryption:&lt;/strong&gt; enabled (this must be chosen at creation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deletion protection:&lt;/strong&gt; on for anything important&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create database&lt;/strong&gt;. It takes a few minutes to reach &lt;strong&gt;Available&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Open the database and copy its &lt;strong&gt;Endpoint&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 4: Connect from EC2
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Connect to your EC2 instance (launch one with &lt;code&gt;ec2-app-sg&lt;/code&gt; in the same VPC if you don't have one).&lt;/li&gt;
&lt;li&gt;Install a MySQL client:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; mariadb105
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Connect using the RDS endpoint:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   mysql &lt;span class="nt"&gt;-h&lt;/span&gt; &amp;lt;your-rds-endpoint&amp;gt; &lt;span class="nt"&gt;-u&lt;/span&gt; admin &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you used Secrets Manager, open the secret in the console and choose &lt;strong&gt;Retrieve secret value&lt;/strong&gt; to get the password.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a table and add data:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;   &lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="n"&gt;appdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;visitors&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
   &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;visitors&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Vishal'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'AWS Builder'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;visitors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You now have a working managed database that only your app server can reach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Turn On Multi-AZ
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Select your database and click &lt;strong&gt;Modify&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Under Availability, choose &lt;strong&gt;Create a standby instance (Multi-AZ)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Apply immediately&lt;/strong&gt; and confirm.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;RDS creates a standby in another AZ and keeps it synchronized. Your endpoint stays the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Test Failover
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Select the database, then &lt;strong&gt;Actions → Reboot&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Check &lt;strong&gt;Reboot with failover?&lt;/strong&gt; and confirm.&lt;/li&gt;
&lt;li&gt;Watch the &lt;strong&gt;Events&lt;/strong&gt; tab and the database's AZ. The standby is promoted, and the AZ changes.&lt;/li&gt;
&lt;li&gt;Re-run your SQL query. Your data is still there, and the &lt;strong&gt;same endpoint&lt;/strong&gt; works.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Expect a short interruption (typically a minute or two) while DNS flips to the new primary. Your application should retry failed connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7 (Optional): Add a Read Replica
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Select the database and choose &lt;strong&gt;Actions → Create read replica&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Give it an identifier such as &lt;code&gt;mydb-rds-replica&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Once available, point &lt;strong&gt;read-heavy queries&lt;/strong&gt; at the replica's endpoint and keep writes on the primary.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Replication is asynchronous, so replicas can lag slightly behind the primary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-AZ vs Read Replica
&lt;/h2&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;Multi-AZ&lt;/th&gt;
&lt;th&gt;Read Replica&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Purpose&lt;/td&gt;
&lt;td&gt;High availability and failover&lt;/td&gt;
&lt;td&gt;Read scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Replication&lt;/td&gt;
&lt;td&gt;Synchronous&lt;/td&gt;
&lt;td&gt;Asynchronous&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Takes traffic normally&lt;/td&gt;
&lt;td&gt;No (standby only)&lt;/td&gt;
&lt;td&gt;Yes (reads)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automatic failover&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No (manual promotion)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Security Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep &lt;strong&gt;Public access set to No&lt;/strong&gt; and place the DB in private subnets.&lt;/li&gt;
&lt;li&gt;Allow access only from application security groups.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Secrets Manager&lt;/strong&gt; for credentials and rotate them.&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;encryption at rest&lt;/strong&gt; (KMS) and enforce &lt;strong&gt;SSL/TLS&lt;/strong&gt; connections.&lt;/li&gt;
&lt;li&gt;Turn on &lt;strong&gt;deletion protection&lt;/strong&gt; and automated backups.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;IAM&lt;/strong&gt; to control who can modify or delete DB instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cost Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Pick the smallest instance that meets your needs and resize later.&lt;/li&gt;
&lt;li&gt;Use Multi-AZ for production, but not for throwaway labs.&lt;/li&gt;
&lt;li&gt;Stop or delete dev databases you aren't using. (A stopped RDS instance is automatically started again after 7 days.)&lt;/li&gt;
&lt;li&gt;Delete old manual snapshots you no longer need.&lt;/li&gt;
&lt;li&gt;Consider Reserved Instances for steady, long-running databases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Issues and Fixes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Connection times out&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;rds-sg&lt;/code&gt; doesn't allow 3306 from your app's SG&lt;/td&gt;
&lt;td&gt;Add the inbound rule with &lt;code&gt;ec2-app-sg&lt;/code&gt; as source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can't connect from your laptop&lt;/td&gt;
&lt;td&gt;Database is private (public access: No)&lt;/td&gt;
&lt;td&gt;Connect through EC2, a bastion, or Session Manager&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Access denied for user&lt;/td&gt;
&lt;td&gt;Wrong username or password&lt;/td&gt;
&lt;td&gt;Re-check credentials or the Secrets Manager value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unknown database&lt;/td&gt;
&lt;td&gt;Initial DB name wasn't set&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;CREATE DATABASE appdb;&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage full warnings&lt;/td&gt;
&lt;td&gt;Autoscaling off or limit reached&lt;/td&gt;
&lt;td&gt;Enable storage autoscaling or increase size&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Clean Up
&lt;/h2&gt;

&lt;p&gt;To avoid charges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Delete the &lt;strong&gt;read replica&lt;/strong&gt; first (if you created one)&lt;/li&gt;
&lt;li&gt;Turn off &lt;strong&gt;deletion protection&lt;/strong&gt;, then delete the &lt;strong&gt;DB instance&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Decide whether to keep a &lt;strong&gt;final snapshot&lt;/strong&gt; (it costs storage) and whether to delete &lt;strong&gt;automated backups&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Delete leftover &lt;strong&gt;manual snapshots&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Delete the &lt;strong&gt;security groups&lt;/strong&gt; and the &lt;strong&gt;EC2 instance&lt;/strong&gt; if no longer needed&lt;/li&gt;
&lt;li&gt;Delete the &lt;strong&gt;Secrets Manager secret&lt;/strong&gt; if you created one just for this lab&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Amazon RDS lets you run production-grade relational databases without managing servers, patches, or backups by hand. With private networking, Multi-AZ, and automated backups, you get a secure and resilient foundation in minutes. Next, try adding a read replica, enabling Performance Insights, or moving to Aurora to see how far managed databases can go.&lt;/p&gt;

&lt;p&gt;If you found this helpful, let's connect and keep learning together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect with me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/vishalpatil-devops-aws/" rel="noopener noreferrer"&gt;vishalpatil-devops-aws&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;dev.to: &lt;a href="https://dev.to/vishal_patil_aws"&gt;@vishal_patil_aws&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/VishalPatil-DevOps-AWS" rel="noopener noreferrer"&gt;VishalPatil-DevOps-AWS&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  vishalcloudjourney
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
