<?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: Uwais</title>
    <description>The latest articles on DEV Community by Uwais (@waisyrr).</description>
    <link>https://dev.to/waisyrr</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%2F3987505%2F1ce362d8-60bc-4489-920a-4feb9526d6f2.png</url>
      <title>DEV Community: Uwais</title>
      <link>https://dev.to/waisyrr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/waisyrr"/>
    <language>en</language>
    <item>
      <title>I Built a Serverless Resume on AWS with Terraform, Lambda, and GitHub Actions</title>
      <dc:creator>Uwais</dc:creator>
      <pubDate>Tue, 16 Jun 2026 13:40:04 +0000</pubDate>
      <link>https://dev.to/waisyrr/how-i-built-a-serverless-resume-on-aws-cloud-resume-challenge-project-g01</link>
      <guid>https://dev.to/waisyrr/how-i-built-a-serverless-resume-on-aws-cloud-resume-challenge-project-g01</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# How I Built an Automated Serverless Resume on AWS (Cloud Resume Challenge)&lt;/span&gt;

The Cloud Resume Challenge is a practical exercise in moving beyond tutorials into production-style cloud engineering. It forces you to design, deploy, and integrate multiple AWS services into a single working system.

This project evolved from a manually deployed serverless setup into a fully automated Infrastructure-as-Code pipeline on AWS using Terraform and GitHub Actions.
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## 🏗️ Architecture Overview&lt;/span&gt;

The system is fully serverless, globally distributed, and provisioned entirely through Infrastructure-as-Code:

&lt;span class="gs"&gt;**S3 → CloudFront → API Gateway → Lambda → DynamoDB**&lt;/span&gt;

&lt;span class="gu"&gt;### Core Components&lt;/span&gt;

&lt;span class="gu"&gt;#### 1. Frontend (S3)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Static resume site built with HTML and Tailwind CSS
&lt;span class="p"&gt;-&lt;/span&gt; Hosted in a private Amazon S3 bucket
&lt;span class="p"&gt;-&lt;/span&gt; No direct public access; served via CloudFront only

&lt;span class="gu"&gt;#### 2. CDN (CloudFront)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Global content delivery via AWS edge locations
&lt;span class="p"&gt;-&lt;/span&gt; HTTPS enforced by default
&lt;span class="p"&gt;-&lt;/span&gt; Aggressive caching for performance optimization

&lt;span class="gu"&gt;#### 3. Database (DynamoDB)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Serverless NoSQL table in pay-per-request mode
&lt;span class="p"&gt;-&lt;/span&gt; Stores a persistent visitor counter (&lt;span class="sb"&gt;`ID: visitors`&lt;/span&gt;)
&lt;span class="p"&gt;-&lt;/span&gt; Low-latency reads/writes for API interactions

&lt;span class="gu"&gt;#### 4. Backend (Lambda)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Python-based AWS Lambda function using &lt;span class="sb"&gt;`boto3`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Performs atomic read/increment operations on DynamoDB
&lt;span class="p"&gt;-&lt;/span&gt; Stateless compute layer triggered via API Gateway

&lt;span class="gu"&gt;#### 5. API Layer (API Gateway)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; HTTP API with &lt;span class="sb"&gt;`/counter`&lt;/span&gt; POST route
&lt;span class="p"&gt;-&lt;/span&gt; Proxy integration directly to Lambda
&lt;span class="p"&gt;-&lt;/span&gt; CORS enabled for browser-based frontend access

&lt;span class="gu"&gt;#### 6. Infrastructure as Code (Terraform)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Entire AWS stack defined declaratively in &lt;span class="sb"&gt;`main.tf`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Uses &lt;span class="sb"&gt;`terraform state`&lt;/span&gt; to manage resource mapping
&lt;span class="p"&gt;-&lt;/span&gt; Handles IAM roles, API routes, Lambda packaging, and S3 deployment

&lt;span class="gu"&gt;#### 7. CI/CD (GitHub Actions)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Automated deployment pipeline for frontend assets
&lt;span class="p"&gt;-&lt;/span&gt; Push-to-deploy workflow into S3
&lt;span class="p"&gt;-&lt;/span&gt; CloudFront cache invalidation after every release
&lt;span class="p"&gt;
---
&lt;/span&gt;
&lt;span class="gu"&gt;## 🧠 Key Engineering Challenges &amp;amp; Fixes&lt;/span&gt;

&lt;span class="gu"&gt;### 1. Git Push Failure: 100MB File Limit (Terraform Provider Bloat)&lt;/span&gt;

While staging the repository, Git accidentally tracked &lt;span class="sb"&gt;`.terraform/`&lt;/span&gt; directories. This introduced a large AWS provider binary (~600MB+), exceeding GitHub’s 100MB file limit.

&lt;span class="gu"&gt;#### Root Cause&lt;/span&gt;
Terraform initializes large provider binaries locally, which can be mistakenly committed if not ignored early.

&lt;span class="gu"&gt;#### Fix&lt;/span&gt;
Even after updating &lt;span class="sb"&gt;`.gitignore`&lt;/span&gt;, the file history still contained the large binaries. A full index reset was required:

&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;bash
&lt;/span&gt;git &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--cached&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
git reset &lt;span class="nt"&gt;--mixed&lt;/span&gt; &amp;lt;clean-commit-hash&amp;gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: clean terraform state and restructure repo"&lt;/span&gt;
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This removed the cached large files from Git tracking and rebuilt a clean commit history.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Migrating to Infrastructure-as-Code (Terraform Import)
&lt;/h3&gt;

&lt;p&gt;A major challenge was converting manually created AWS resources into Terraform-managed infrastructure without duplication errors.&lt;/p&gt;

&lt;h4&gt;
  
  
  Approach
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Defined equivalent resources in &lt;code&gt;main.tf&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Used &lt;code&gt;terraform import&lt;/code&gt; to map existing AWS resources into Terraform state&lt;/li&gt;
&lt;li&gt;Gradually aligned live infrastructure with declarative definitions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This transitioned the system from “click-ops” to fully reproducible infrastructure.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. API Gateway + Lambda Response Handling
&lt;/h3&gt;

&lt;p&gt;Initial frontend integration produced errors like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Views: undefined&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SyntaxError: "undefined" is not valid JSON&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Root Cause
&lt;/h4&gt;

&lt;p&gt;HTTP API proxy integration already returns parsed JSON. The frontend incorrectly attempted redundant parsing of &lt;code&gt;response.body&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Fix
&lt;/h4&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Removing unnecessary parsing resolved the issue and stabilized the UI.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Key Takeaways
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Automation-first architecture
&lt;/h3&gt;

&lt;p&gt;Shifting from manual deployments to Git-driven Infrastructure-as-Code enables full environment reproducibility in seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  IAM least privilege design
&lt;/h3&gt;

&lt;p&gt;Lambda execution role was explicitly scoped to only the required DynamoDB table, minimizing blast radius.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-world DevOps friction
&lt;/h3&gt;

&lt;p&gt;The project surfaced production-grade issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git history cleanup for large binaries&lt;/li&gt;
&lt;li&gt;CORS and API integration debugging&lt;/li&gt;
&lt;li&gt;CDN cache invalidation strategies&lt;/li&gt;
&lt;li&gt;Terraform state management and imports&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 Live Project Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌐 Live Site: &lt;a href="https://d1l6jcvu4zf64q.cloudfront.net/" rel="noopener noreferrer"&gt;https://d1l6jcvu4zf64q.cloudfront.net/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;⚙️ API Endpoint: &lt;a href="https://t9bxl7c440.execute-api.eu-north-1.amazonaws.com/counter" rel="noopener noreferrer"&gt;https://t9bxl7c440.execute-api.eu-north-1.amazonaws.com/counter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 GitHub Repo: &lt;a href="https://github.com/waisyrr/cloud-resum" rel="noopener noreferrer"&gt;https://github.com/waisyrr/cloud-resum&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📌 Closing
&lt;/h2&gt;

&lt;p&gt;This project demonstrates how a set of core AWS services can be composed into a production-grade serverless system.&lt;/p&gt;

&lt;p&gt;The main outcome was not the resume itself, but the operational model behind it: fully automated, reproducible cloud infrastructure built with Infrastructure-as-Code, CI/CD, and stateless compute design.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>cloud</category>
      <category>aws</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
