<?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>Forem: Nauman Tanwir</title>
    <description>The latest articles on Forem by Nauman Tanwir (@ntanwir10).</description>
    <link>https://forem.com/ntanwir10</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F440197%2F599d6164-78d5-4271-be7f-0d082760c13a.png</url>
      <title>Forem: Nauman Tanwir</title>
      <link>https://forem.com/ntanwir10</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ntanwir10"/>
    <language>en</language>
    <item>
      <title>Introducing GuardScan: 100% Free, Privacy-First AI Code Review &amp; Security Scanning CLI</title>
      <dc:creator>Nauman Tanwir</dc:creator>
      <pubDate>Mon, 17 Nov 2025 03:02:20 +0000</pubDate>
      <link>https://forem.com/ntanwir10/introducing-guardscan-100-free-privacy-first-ai-code-review-security-scanning-cli-4dai</link>
      <guid>https://forem.com/ntanwir10/introducing-guardscan-100-free-privacy-first-ai-code-review-security-scanning-cli-4dai</guid>
      <description>&lt;h2&gt;
  
  
  Introducing GuardScan: Privacy-First Security Scanning &amp;amp; AI Code Review
&lt;/h2&gt;

&lt;p&gt;Hey dev.to community! 👋&lt;/p&gt;

&lt;p&gt;I'm excited to share &lt;strong&gt;GuardScan v1.0&lt;/strong&gt;, a tool I built to solve a problem I ran into over and over again: finding a security scanner and AI reviewer that's strong, affordable, and respects developer privacy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Most security and code review tools fall short:&lt;/p&gt;

&lt;p&gt;🚫 Expensive&lt;br&gt;
🚫 Privacy concerns&lt;br&gt;
🚫 Usage limits&lt;br&gt;
🚫 Vendor lock-in&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: GuardScan
&lt;/h2&gt;

&lt;p&gt;GuardScan is a &lt;strong&gt;free, open-source CLI&lt;/strong&gt; that offers full security scanning and AI-powered code review while keeping everything on your machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Principles
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Always Free&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No credit system
&lt;/li&gt;
&lt;li&gt;No subscriptions
&lt;/li&gt;
&lt;li&gt;No enterprise-only features
&lt;/li&gt;
&lt;li&gt;Unlimited repositories
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Privacy-First&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Never upload your source code
&lt;/li&gt;
&lt;li&gt;Offline static analysis
&lt;/li&gt;
&lt;li&gt;Optional, anonymized telemetry
&lt;/li&gt;
&lt;li&gt;All code stays local
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Bring Your Own Key (BYOK)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use OpenAI, Claude, Gemini, or local AI via Ollama
&lt;/li&gt;
&lt;li&gt;Pay your provider directly
&lt;/li&gt;
&lt;li&gt;GuardScan charges nothing
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Start
&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;### Install globally&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; guardscan

&lt;span class="c"&gt;### Initialize&lt;/span&gt;
guardscan init

&lt;span class="c"&gt;### Run security scan (offline)&lt;/span&gt;
guardscan security

&lt;span class="c"&gt;### Configure AI provider (optional)&lt;/span&gt;
guardscan config

&lt;span class="c"&gt;### Run AI-enhanced review&lt;/span&gt;
guardscan run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Can GuardScan Do?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔒 Security Scanning (Free &amp;amp; Offline)
&lt;/h3&gt;

&lt;p&gt;Built-in scanners:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secrets detection&lt;/li&gt;
&lt;li&gt;Dependency vulnerabilities&lt;/li&gt;
&lt;li&gt;OWASP Top 10 checks&lt;/li&gt;
&lt;li&gt;Docker security&lt;/li&gt;
&lt;li&gt;Infrastructure as Code analysis&lt;/li&gt;
&lt;li&gt;API security&lt;/li&gt;
&lt;li&gt;Code metrics&lt;/li&gt;
&lt;li&gt;Code smells&lt;/li&gt;
&lt;li&gt;License compliance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤖 AI-Enhanced Features (BYOK)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;guardscan explain &amp;lt;file&amp;gt;
guardscan review &amp;lt;file&amp;gt;
guardscan commit
guardscan docs &amp;lt;file&amp;gt;
guardscan test-gen &amp;lt;file&amp;gt;
guardscan refactor &amp;lt;file&amp;gt;
guardscan threat-model
guardscan migrate
guardscan chat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🌍 Language Support
&lt;/h2&gt;

&lt;p&gt;AST parsers for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript / JavaScript&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Go&lt;/li&gt;
&lt;li&gt;Rust&lt;/li&gt;
&lt;li&gt;Ruby&lt;/li&gt;
&lt;li&gt;PHP&lt;/li&gt;
&lt;li&gt;C#&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture: Privacy by Design
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;┌─────────────────────────────────┐
│      YOUR MACHINE               │
│                                 │
│  ┌─────────────────────────┐    │
│  │   GuardScan CLI         │    │
│  │   • Static Analysis     │    │
│  │   • Security Scanning   │    │
│  │   • AI Integration      │    │
│  └─────────────────────────┘    │
│             │                   │
└─────────────┼───────────────────┘
              │
    ┌─────────┴─────────┐
    │                   │
    ▼                   ▼
┌─────────────┐   ┌──────────────┐
│ Your AI     │   │ Telemetry    │
│ Provider    │   │ &lt;span class="o"&gt;(&lt;/span&gt;Optional&lt;span class="o"&gt;)&lt;/span&gt;   │
│ &lt;span class="o"&gt;(&lt;/span&gt;Optional&lt;span class="o"&gt;)&lt;/span&gt;  │   │              │
└─────────────┘   └──────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your code never leaves your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Let’s say you have a 10k-line TypeScript project.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Install and set up
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; guardscan
guardscan init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Run a free security scan
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;guardscan security

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Output:
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Secrets scan: 3 issues found
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Dependency scan: 12 vulnerabilities
&lt;/h4&gt;

&lt;h4&gt;
  
  
  OWASP scan: 5 potential issues
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Code quality: 89/100
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Report saved: security-report.md
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Configure AI
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;guardscan config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Run AI review
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;guardscan run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Output:
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Analyzing codebase...
&lt;/h5&gt;

&lt;h5&gt;
  
  
  Found 47 improvement suggestions
&lt;/h5&gt;

&lt;h5&gt;
  
  
  Identified 8 security concerns
&lt;/h5&gt;

&lt;h5&gt;
  
  
  Report saved: review-report.md
&lt;/h5&gt;

&lt;p&gt;Total cost:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GuardScan: $0&lt;/li&gt;
&lt;li&gt;Static analysis: $0&lt;/li&gt;
&lt;li&gt;AI review (with Ollama): $0&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Technology Stack
&lt;/h4&gt;

&lt;p&gt;CLI (34k+ LOC):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript 5.3+&lt;/li&gt;
&lt;li&gt;Node.js 18+&lt;/li&gt;
&lt;li&gt;Commander.js&lt;/li&gt;
&lt;li&gt;Jest test suite&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;GuardScan&lt;/th&gt;
&lt;th&gt;SonarQube&lt;/th&gt;
&lt;th&gt;Snyk&lt;/th&gt;
&lt;th&gt;GitHub Copilot&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Limited / Paid&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy&lt;/td&gt;
&lt;td&gt;Local&lt;/td&gt;
&lt;td&gt;Cloud upload&lt;/td&gt;
&lt;td&gt;Cloud upload&lt;/td&gt;
&lt;td&gt;Cloud upload&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Offline&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Provider&lt;/td&gt;
&lt;td&gt;Any&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;OpenAI only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open Source&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;td&gt;LGPL&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usage Limits&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Roadmap&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; GitHub Actions integration&lt;/li&gt;
&lt;li&gt; GitLab CI/CD support&lt;/li&gt;
&lt;li&gt; VSCode extension&lt;/li&gt;
&lt;li&gt; Web UI for reports&lt;/li&gt;
&lt;li&gt; More language parsers (Swift, Kotlin)&lt;/li&gt;
&lt;li&gt; Custom rule engine upgrades&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contributing&lt;/p&gt;

&lt;p&gt;GuardScan is &lt;strong&gt;open source&lt;/strong&gt; (MIT License) and contributions are welcome!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Report bugs&lt;/strong&gt;: &lt;a href="https://github.com/ntanwir10/GuardScan/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Request features&lt;/strong&gt;: &lt;a href="https://github.com/ntanwir10/GuardScan/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Submit PRs&lt;/strong&gt;: All contributions welcome!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The codebase is a well-structured TypeScript with 70%+ test coverage. Check out the &lt;a href="https://github.com/ntanwir10/GuardScan/blob/main/docs/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING.md&lt;/a&gt; for details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;As a developer, I was frustrated with security tools that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Charged money for basics&lt;/li&gt;
&lt;li&gt;Uploaded code to remote servers&lt;/li&gt;
&lt;li&gt;Imposed usage limits&lt;/li&gt;
&lt;li&gt;Forced a single vendor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Security tools should be accessible to everyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started Today
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g guardscan
guardscan init
guardscan security
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⭐ &lt;a href="https://github.com/ntanwir10/GuardScan" rel="noopener noreferrer"&gt;Star the repo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Feedback Matters
&lt;/h2&gt;

&lt;p&gt;What features would you like to see? What security checks are missing? Drop a comment below!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Made with ❤️ by developers, for developers&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>security</category>
      <category>opensource</category>
    </item>
    <item>
      <title>ThoughtTap: I Built a VS Code Extension That Stops Me From Writing Terrible AI Prompts (and it's kinda working)</title>
      <dc:creator>Nauman Tanwir</dc:creator>
      <pubDate>Mon, 29 Sep 2025 21:01:14 +0000</pubDate>
      <link>https://forem.com/ntanwir10/i-built-a-vs-code-extension-that-stops-me-from-writing-terrible-ai-prompts-and-its-kinda-working-529i</link>
      <guid>https://forem.com/ntanwir10/i-built-a-vs-code-extension-that-stops-me-from-writing-terrible-ai-prompts-and-its-kinda-working-529i</guid>
      <description>&lt;p&gt;&lt;em&gt;Launching on Cursor &amp;amp; Windsurf next week, Product Hunt in 2-3 weeks — would love your feedback before then!&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🧠 &lt;strong&gt;What&lt;/strong&gt;: VS Code extension that makes AI prompts context-aware&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Why&lt;/strong&gt;: Stop wasting time explaining your tech stack to AI tools&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;How&lt;/strong&gt;: Analyzes your project automatically, optimizes prompts locally&lt;/li&gt;
&lt;li&gt;💰 &lt;strong&gt;Cost&lt;/strong&gt;: Free tier forever, $6.99/month for Pro features&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Status&lt;/strong&gt;: Live on VS Code, launching on Cursor/Windsurf next week, Product Hunt in 2-3 weeks&lt;/li&gt;
&lt;li&gt;🙏 &lt;strong&gt;Need&lt;/strong&gt;: Your feedback before official launches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VS Code&lt;/strong&gt;: &lt;a href="https://marketplace.visualstudio.com/items?itemName=ntanwir.thoughttap" rel="noopener noreferrer"&gt;VS Code Marketplace&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cursor/Windsurf&lt;/strong&gt;: Coming next week via OpenVSX Registry&lt;/li&gt;
&lt;li&gt;Check out the website for more information - &lt;a href="https://thoughttap.com/" rel="noopener noreferrer"&gt;ThoughtTap&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Problem That Wouldn't Leave Me Alone
&lt;/h2&gt;

&lt;p&gt;You know that moment when you copy-paste code into ChatGPT with "fix this bug" and get back a generic solution that completely ignores your TypeScript/React/AWS stack? Yeah, me too. Every. Single. Day.&lt;/p&gt;

&lt;p&gt;I'd spend 10 minutes explaining context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Actually, I'm using React 18 with TypeScript"&lt;/li&gt;
&lt;li&gt;"This is a microservices architecture"
&lt;/li&gt;
&lt;li&gt;"We're deploying to AWS Lambda"&lt;/li&gt;
&lt;li&gt;"We use Prisma for database queries."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, finally, get a useful response. Rinse and repeat 20 times a day.&lt;/p&gt;

&lt;p&gt;There had to be a better way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Aha!" Moment
&lt;/h2&gt;

&lt;p&gt;The problem wasn't the AI — it was the context gap. AI tools don't know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What language/framework are you using&lt;/li&gt;
&lt;li&gt;Your project architecture&lt;/li&gt;
&lt;li&gt;Your deployment environment&lt;/li&gt;
&lt;li&gt;Your testing setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They're flying blind because we give them nothing to work with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter &lt;a href="https://thoughttap.com/" rel="noopener noreferrer"&gt;ThoughtTap&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I built a VS Code extension that automatically analyzes your project and transforms basic prompts into context-aware requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before:&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;Help me optimize this database query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After ThoughtTap:&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;Help me optimize this PostgreSQL query in a Node.js TypeScript 

application using Prisma ORM. The query runs in a microservices architecture deployed on AWS Lambda with connection pooling

constraints. The current query execution time is 2.3s and needs to be 

under 500ms. Consider database indexes, query structure, and Prisma-

specific optimizations.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI now has everything it needs to give me a useful answer on the first try.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works (The Technical Bits)
&lt;/h2&gt;

&lt;p&gt;ThoughtTap hooks into VS Code's extension API and analyzes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Language Detection&lt;/strong&gt;: File extensions + syntax patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework Recognition&lt;/strong&gt;: Parses &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;requirements.txt&lt;/code&gt;, &lt;code&gt;pom.xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project Structure&lt;/strong&gt;: Workspace layout, dependencies, architecture patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Context&lt;/strong&gt;: Selected code blocks for specific optimization&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All processing happens &lt;strong&gt;locally in VS Code&lt;/strong&gt; — your code never leaves your machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ProjectContext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                    &lt;span class="c1"&gt;// 'typescript'&lt;/span&gt;
  &lt;span class="nl"&gt;frameworks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;                &lt;span class="c1"&gt;// ['React', 'Next.js']&lt;/span&gt;
  &lt;span class="nl"&gt;projectType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;backend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;...;&lt;/span&gt; &lt;span class="c1"&gt;// 'web'&lt;/span&gt;
  &lt;span class="nl"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;              &lt;span class="c1"&gt;// ['prisma', 'aws-sdk']&lt;/span&gt;
  &lt;span class="nl"&gt;currentFile&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;FileContext&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;The optimization engine uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rule-based processing&lt;/strong&gt; (&amp;lt;100ms) for grammar, structure, clarity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template matching&lt;/strong&gt; for common patterns (debugging, code review, architecture)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI provider integration&lt;/strong&gt; (Pro) for advanced optimization&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h2&gt;
  
  
  Real-World Impact
&lt;/h2&gt;

&lt;p&gt;Here's what early testers are reporting (mostly VS Code users, gathering Cursor/Windsurf feedback next week):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⏱️ &lt;strong&gt;Time saved&lt;/strong&gt;: 10-15 minutes per complex AI interaction&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;First-response quality&lt;/strong&gt;: 3-4x improvement in useful answers&lt;/li&gt;
&lt;li&gt;🔄 &lt;strong&gt;Back-and-forth reduction&lt;/strong&gt;: From 5+ clarifications to 1-2&lt;/li&gt;
&lt;li&gt;💰 &lt;strong&gt;API cost savings&lt;/strong&gt;: Fewer tokens wasted on bad prompts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why I'm Building This Publicly
&lt;/h2&gt;

&lt;p&gt;I'm taking the bootstrap approach — no VC funding, 100% user-focused. This means:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You&lt;/strong&gt; shape the product through feedback&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your needs&lt;/strong&gt; drive the roadmap&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy-first&lt;/strong&gt; — local processing, your AI keys&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fair pricing&lt;/strong&gt; — $6.99/month Pro (30% less than competitors)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Multi-Editor From Day One
&lt;/h3&gt;

&lt;p&gt;I'm launching on VS Code first, then expanding to Cursor and Windsurf next week via the &lt;strong&gt;OpenVSX Registry&lt;/strong&gt;. Why? Because developers are moving to these AI-powered editors, ThoughtTap should work wherever you code.&lt;/p&gt;

&lt;p&gt;If you're using Cursor or Windsurf, your feedback is especially valuable — let me know what works differently in your editor!&lt;/p&gt;

&lt;h2&gt;
  
  
  Free vs Pro: What You Get
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Free Tier (Always Free)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Core optimization engine&lt;/li&gt;
&lt;li&gt;✅ 10 developer templates&lt;/li&gt;
&lt;li&gt;✅ Context analysis (language, frameworks)&lt;/li&gt;
&lt;li&gt;✅ Up to 5 custom rules&lt;/li&gt;
&lt;li&gt;✅ Right-click optimization&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pro Tier ($6.99/month)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✨ Advanced DevOps &amp;amp; architecture rules&lt;/li&gt;
&lt;li&gt;✨ Cloud deployment optimization (AWS/Azure/GCP)&lt;/li&gt;
&lt;li&gt;✨ 25+ specialized templates&lt;/li&gt;
&lt;li&gt;✨ AI provider integration (OpenAI/Anthropic/Google)&lt;/li&gt;
&lt;li&gt;✨ Up to 20 custom rules&lt;/li&gt;
&lt;li&gt;✨ Settings sync + 90-day history&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Bigger Vision
&lt;/h2&gt;

&lt;p&gt;ThoughtTap starts with developers because that's where the pain is sharpest. But the vision extends beyond code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our Strategic Roadmap&lt;/strong&gt; (see &lt;a href="https://github.com/ntanwir10/ThoughtTap#-strategic-roadmap" rel="noopener noreferrer"&gt;full roadmap on GitHub&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 1 (Months 1-12)&lt;/strong&gt;: "Tap into AI-enhanced development intelligence"&lt;br&gt;&lt;br&gt;
Focus on VS Code, Cursor, and Windsurf with deep developer workflow integration&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 2 (Year 2+)&lt;/strong&gt;: Web app + Chrome extension for universal use&lt;/p&gt;

&lt;p&gt;Imagine the same context-aware optimization for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business prompts (reports, analysis, strategy)&lt;/li&gt;
&lt;li&gt;Creative work (writing, design briefs)&lt;/li&gt;
&lt;li&gt;Academic research (citations, analysis)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But first, I need to nail the developer experience. That's where you come in.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Need Your Feedback
&lt;/h2&gt;

&lt;p&gt;Before the Product Hunt launch next week, I'm looking for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technical Feedback:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the context analysis catch your project setup correctly?&lt;/li&gt;
&lt;li&gt;Are the optimization rules actually useful?&lt;/li&gt;
&lt;li&gt;What frameworks/languages should I prioritize?&lt;/li&gt;
&lt;li&gt;Performance issues? (It should be &amp;lt;100ms for most operations)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;UX Feedback:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the workflow intuitive?&lt;/li&gt;
&lt;li&gt;What's confusing or unclear?&lt;/li&gt;
&lt;li&gt;What features are you missing?&lt;/li&gt;
&lt;li&gt;Where does it feel clunky?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Strategic Feedback:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Would you actually pay $6.99/month for the Pro features?&lt;/li&gt;
&lt;li&gt;What would make this a "must-have" tool?&lt;/li&gt;
&lt;li&gt;What's missing that would prevent you from using it daily?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It Now (Pre-Launch Access)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  VS Code Users
&lt;/h3&gt;

&lt;p&gt;ThoughtTap is live on the VS Code Marketplace:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open VS Code&lt;/li&gt;
&lt;li&gt;Search "ThoughtTap" in Extensions&lt;/li&gt;
&lt;li&gt;Install&lt;/li&gt;
&lt;li&gt;Select any text → Right-click → "ThoughtTap: Optimize"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Or use the keyboard shortcut: &lt;code&gt;Ctrl+Shift+O&lt;/code&gt; (Cmd+Shift+O on Mac)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation:&lt;/strong&gt; &lt;a href="https://marketplace.visualstudio.com/items?itemName=ntanwir.thoughttap" rel="noopener noreferrer"&gt;VS Code Marketplace&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cursor &amp;amp; Windsurf Users
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Coming Next Week!&lt;/strong&gt; ThoughtTap will be available on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenVSX Registry&lt;/strong&gt; (for both Cursor and Windsurf)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cursor Marketplace&lt;/strong&gt; (OpenVSX-powered)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windsurf Marketplace&lt;/strong&gt; (marketplace.windsurf.com)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm publishing to OpenVSX next week to reach Cursor and Windsurf users. If you're using these editors, drop a comment and I'll notify you when it's live!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Ask
&lt;/h2&gt;

&lt;p&gt;If you try ThoughtTap:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;⭐ &lt;strong&gt;Drop a comment&lt;/strong&gt; with your honest feedback (brutal honesty welcome!)&lt;/li&gt;
&lt;li&gt;🐛 &lt;strong&gt;Report bugs&lt;/strong&gt; via &lt;a href="https://github.com/ntanwir10/ThoughtTap/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💡 &lt;strong&gt;Share ideas&lt;/strong&gt; for features you'd actually use (GitHub Issues or &lt;a href="https://thoughttap.com/contact" rel="noopener noreferrer"&gt;contact page&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Spread the word&lt;/strong&gt; if you find it useful&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Stay connected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🐛 &lt;strong&gt;Report Bugs&lt;/strong&gt;: &lt;a href="https://github.com/ntanwir10/ThoughtTap/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;Get in Touch&lt;/strong&gt;: &lt;a href="https://thoughttap.com/contact" rel="noopener noreferrer"&gt;thoughttap.com/contact&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🗺️ &lt;strong&gt;View Roadmap&lt;/strong&gt;: &lt;a href="https://github.com/ntanwir10/ThoughtTap#-strategic-roadmap" rel="noopener noreferrer"&gt;GitHub Roadmap&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;⭐ &lt;strong&gt;Star on GitHub&lt;/strong&gt;: &lt;a href="https://github.com/ntanwir10/ThoughtTap" rel="noopener noreferrer"&gt;github.com/ntanwir10/ThoughtTap&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;This Week:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Polish based on your feedback&lt;/li&gt;
&lt;li&gt;Fix any critical bugs&lt;/li&gt;
&lt;li&gt;Add most-requested features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Next Week:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Publish to OpenVSX Registry&lt;/li&gt;
&lt;li&gt;Launch on Cursor &amp;amp; Windsurf marketplaces&lt;/li&gt;
&lt;li&gt;Support multi-editor user base&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Weeks 2-3:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product Hunt launch&lt;/li&gt;
&lt;li&gt;Official marketing push&lt;/li&gt;
&lt;li&gt;Community building campaign&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Month 2-3:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Advanced AI provider integrations&lt;/li&gt;
&lt;li&gt;Custom template builder&lt;/li&gt;
&lt;li&gt;Team collaboration features&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Note on Sustainability
&lt;/h2&gt;

&lt;p&gt;I'm building ThoughtTap as a sustainable business, not a VC-funded rocket ship. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No pressure&lt;/strong&gt; to pivot away from what users need&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-term thinking&lt;/strong&gt; over quick exits&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fair pricing&lt;/strong&gt; that reflects actual value&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User privacy&lt;/strong&gt; over data monetization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this resonates with you, give ThoughtTap a shot and let me know what you think.&lt;/p&gt;




&lt;h2&gt;
  
  
  Discussion
&lt;/h2&gt;

&lt;p&gt;I'm curious about your experiences:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What's your biggest frustration with AI coding assistants?&lt;/li&gt;
&lt;li&gt;How much time do you spend clarifying context to AI tools daily?&lt;/li&gt;
&lt;li&gt;Would you trust a VS Code extension with your project analysis?&lt;/li&gt;
&lt;li&gt;What would make you choose ThoughtTap over just learning better prompting?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Are you using Cursor or Windsurf?&lt;/strong&gt; What features would you need most?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's discuss in the comments! 👇&lt;/p&gt;




</description>
      <category>vscode</category>
      <category>cursor</category>
      <category>development</category>
      <category>ai</category>
    </item>
    <item>
      <title>Building an AI-Powered Anomaly Detection System with Redis 8: Beyond Traditional Caching</title>
      <dc:creator>Nauman Tanwir</dc:creator>
      <pubDate>Sun, 10 Aug 2025 21:31:25 +0000</pubDate>
      <link>https://forem.com/ntanwir10/building-an-ai-powered-anomaly-detection-system-with-redis-8-beyond-traditional-caching-1j7i</link>
      <guid>https://forem.com/ntanwir10/building-an-ai-powered-anomaly-detection-system-with-redis-8-beyond-traditional-caching-1j7i</guid>
      <description>&lt;h1&gt;
  
  
  Building an AI-Powered Anomaly Detection System with Redis 8: Beyond Traditional Caching
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/redis-2025-07-23"&gt;Redis AI Challenge&lt;/a&gt;: Beyond the Cache&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I've built a &lt;strong&gt;production-ready AI Anomaly Detection System&lt;/strong&gt; that transforms Redis 8 from a simple cache into a powerful real-time data processing and machine learning platform. This system monitors microservices, detects anomalies using AI, and provides instant alerts - all powered by Redis 8's advanced features.&lt;/p&gt;

&lt;h3&gt;
  
  
  🚀 Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Anomaly Detection&lt;/strong&gt;: Uses Isolation Forest ML algorithm to detect system anomalies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Service Monitoring&lt;/strong&gt;: Tracks API endpoints, status codes, response times, and business metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis Streams + Pub/Sub&lt;/strong&gt;: Real-time data ingestion and instant alert broadcasting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count-Min Sketches&lt;/strong&gt;: Memory-efficient probabilistic data structures for high-frequency metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RedisGears Integration&lt;/strong&gt;: Server-side data aggregation and processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production-Ready SDKs&lt;/strong&gt;: Python and JavaScript clients for easy integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern Dashboard&lt;/strong&gt;: Real-time visualization with WebSocket updates&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ntanwir10" rel="noopener noreferrer"&gt;
        ntanwir10
      &lt;/a&gt; / &lt;a href="https://github.com/ntanwir10/AI-Anamoly-Detector" rel="noopener noreferrer"&gt;
        AI-Anamoly-Detector
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A highly efficient, real-time anomaly detection system for distributed microservices architecture that leverages Redis's advanced probabilistic data structures (RedisBloom) for memory-efficient data collection and RedisGears for in-database processing. An AI model analyzes data patterns to identify and predict system failures before they cascade.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;AI-Driven Distributed System Anomaly Detection&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A &lt;strong&gt;production-ready&lt;/strong&gt;, real-time anomaly detection system for distributed microservices architecture that leverages Redis's advanced probabilistic data structures (RedisBloom) for memory-efficient data collection and RedisGears for in-database processing. An AI model analyzes data patterns to identify and predict system failures before they cascade.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🏆 Built for the &lt;a href="https://dev.to/challenges/redis-2025-07-23?" rel="nofollow"&gt;Redis AI Challenge&lt;/a&gt;&lt;/strong&gt; - This project showcases Redis as a high-performance, multi-model engine for complex data processing and analysis pipelines, demonstrating Redis capabilities far beyond traditional caching.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Competing in the &lt;strong&gt;"Beyond the Cache"&lt;/strong&gt; challenge prompt, demonstrating how Redis can do much more than traditional caching by serving as a primary database, full-text search engine, real-time streams processor, and pub/sub messaging system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This system is designed for &lt;strong&gt;real-world deployment&lt;/strong&gt; and includes comprehensive integration options, client SDKs, and enterprise-grade features for monitoring distributed systems at scale.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📑 Table of Contents&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/AI-Anamoly-Detector#-production-ready-features" rel="noopener noreferrer"&gt;🌟 Production-Ready Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/AI-Anamoly-Detector#-integration-guides" rel="noopener noreferrer"&gt;📚 Integration Guides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/AI-Anamoly-Detector#-real-world-use-cases" rel="noopener noreferrer"&gt;🏭 Real-World Use Cases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ntanwir10/AI-Anamoly-Detector" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The system is fully containerized and can be deployed with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📱 Dashboard Screenshots
&lt;/h3&gt;

&lt;p&gt;The dashboard provides real-time insights into:&lt;/p&gt;

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

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

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqmlwhq5d29b2zvuthxq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqmlwhq5d29b2zvuthxq.png" alt="Logs from the AI Service based on Isolation Model from Scikit-learn using Python"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flfpazshrse6a88ei3d9x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flfpazshrse6a88ei3d9x.png" alt="Logs from Node.js and express.js Microservice"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔗 Quick Start
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the repository&lt;/span&gt;
git clone https://github.com/ntanwir10/AI-Anamoly-Detector
&lt;span class="nb"&gt;cd &lt;/span&gt;ai-anomaly-detector

&lt;span class="c"&gt;# Start all services&lt;/span&gt;
docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;

&lt;span class="c"&gt;# Access the dashboard&lt;/span&gt;
open http://localhost:3001

&lt;span class="c"&gt;# Send test metrics&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:4000/metrics &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"service": "test", "endpoint": "GET:/api/test", "status_code": 200}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🏗️ How This Works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Architecture Overview&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The system is composed of &lt;strong&gt;six main components&lt;/strong&gt; with &lt;strong&gt;real data integration capabilities&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Real Data Sources + Demo Simulation:&lt;/strong&gt; Production data sources (APM, business metrics, logs) + simulated microservices for testing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Data Collector:&lt;/strong&gt; Production-ready collector with real data APIs, business metrics, and log processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis Core:&lt;/strong&gt; The central engine, running with the RedisBloom and RedisGears modules. It ingests real data, aggregates it, and stores the system's "fingerprint."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Anomaly Service:&lt;/strong&gt; A Python service that reads the fingerprint data from Redis, trains an anomaly detection model, and identifies outlier patterns in real data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard UI:&lt;/strong&gt; A React frontend with real-time WebSocket updates showing live system health and anomalies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real Data Integration Layer:&lt;/strong&gt; APM providers, business applications, infrastructure monitoring, and enterprise systems&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Data Flow Architecture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo2ximv37ucxxln527wk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo2ximv37ucxxln527wk.png" alt="data flow architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Enhanced Data Flow Diagram&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7a3q4669uf5idlmhhhf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7a3q4669uf5idlmhhhf.png" alt="enhanced data flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How It Works&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Real Data Processing&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Production Data Ingestion&lt;/strong&gt;: Real applications send metrics via enhanced APIs every few seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Data Collection&lt;/strong&gt;: The Enhanced Data Collector processes multiple data types and sends commands to Redis:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CF.ADD service-calls service:endpoint&lt;/code&gt; (Real service interactions)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CMS.INCRBY api-frequency endpoint 1&lt;/code&gt; (Real API usage patterns)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CMS.INCRBY business-metrics metric_name 1&lt;/code&gt; (Business KPIs)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;XADD detailed-metrics * data &amp;lt;real_metrics&amp;gt;&lt;/code&gt; (Full-fidelity production data)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-Database Aggregation&lt;/strong&gt;: Every 5 seconds, RedisGears creates system fingerprints from real data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Analysis&lt;/strong&gt;: ML models learn from real production patterns and detect anomalies in live data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Alerting&lt;/strong&gt;: Production alerts with business context and severity assessment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visualization&lt;/strong&gt;: Dashboard shows real production metrics and anomalies&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Demo Mode&lt;/strong&gt; (For Testing)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Traffic Generation&lt;/strong&gt;: Microservice A makes &lt;code&gt;GET /api/v1/users&lt;/code&gt; calls to Microservice B every 2 seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Collection&lt;/strong&gt;: The Data Collector observes demo traffic and sends commands to Redis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-Database Aggregation&lt;/strong&gt;: RedisGears creates system fingerprints every 5 seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Analysis&lt;/strong&gt;: ML models detect anomalies in simulated traffic patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Alerting&lt;/strong&gt;: Demo alerts are published to Redis Pub/Sub for testing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visualization&lt;/strong&gt;: Dashboard displays real-time demo data and anomalies&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How I Used Redis 8
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🎯 Beyond Traditional Caching
&lt;/h3&gt;

&lt;p&gt;This project demonstrates Redis 8's capabilities far beyond simple key-value storage:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Redis Streams for Real-Time Data Processing&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Continuous data ingestion from multiple sources
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_stream_blocking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xread&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;STREAM_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;last_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;last_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;entry_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;entry_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Redis Streams act as a distributed log, allowing the AI service to process metrics in real-time without losing data. This is crucial for anomaly detection where timing is everything.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Count-Min Sketches for Memory-Efficient Analytics&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Initialize probabilistic data structures
&lt;/span&gt;&lt;span class="nf"&gt;redis_cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CMS.INITBYDIM&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;endpoint-frequency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100000&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="nf"&gt;redis_cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CMS.INITBYDIM&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status-codes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100000&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="c1"&gt;# Aggregate high-frequency metrics efficiently
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_count_min_sketch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;redis_cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CMS.QUERY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of storing every single API call (which could be millions per day), Count-Min Sketches provide approximate counts with guaranteed error bounds. This allows monitoring of high-frequency metrics without memory explosion.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Pub/Sub for Instant Alert Broadcasting&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Publish anomaly alerts to all subscribers
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pred&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Anomaly detected
&lt;/span&gt;    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Anomaly detected: Outlier fingerprint observed.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PUBSUB_CHANNEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the AI model detects an anomaly, Redis Pub/Sub instantly broadcasts the alert to all dashboard clients and monitoring systems, ensuring zero-latency notification.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;RedisGears for Server-Side Processing&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Server-side aggregation every 5 seconds
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;aggregate_tick&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_fingerprint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;write_to_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vec&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Aggregation completed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RedisGears runs Python code directly in Redis, performing real-time aggregation of metrics into system "fingerprints" that the AI model can analyze. This eliminates the need for external aggregation services.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. &lt;strong&gt;Hybrid Data Model&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The system combines multiple Redis data structures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Streams&lt;/strong&gt;: Time-series data ingestion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count-Min Sketches&lt;/strong&gt;: Probabilistic counters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pub/Sub&lt;/strong&gt;: Real-time messaging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strings&lt;/strong&gt;: Configuration and metadata&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hashes&lt;/strong&gt;: Service-specific data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔬 AI Integration Architecture
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Machine Learning Pipeline
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Training phase with Redis Streams
&lt;/span&gt;&lt;span class="n"&gt;training_vectors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;training_vectors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;training_target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;last_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;read_stream_blocking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_vector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;training_vectors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Train Isolation Forest model
&lt;/span&gt;&lt;span class="n"&gt;X_train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;training_vectors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;IsolationForest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contamination&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Real-time anomaly detection
&lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_vector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;X_new&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;vec&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;pred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 1=normal, -1=anomaly
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI service continuously reads from Redis Streams, trains on normal system behavior, and then monitors for deviations in real-time.&lt;/p&gt;

&lt;h3&gt;
  
  
  📊 Real-World Use Cases
&lt;/h3&gt;

&lt;h4&gt;
  
  
  E-Commerce Platform Monitoring
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Monitor checkout flow anomalies&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;anomalyClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AnomalyClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://anomaly-detector.company.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Track payment processing&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anomalyClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMetric&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;payment-processor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST:/api/payments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;response_time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;245&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;99.99&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Business metrics&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anomalyClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendBusinessMetric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;daily_revenue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;45000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;40000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Financial Services
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Monitor transaction processing
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_metric&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;service&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;transaction-engine&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;endpoint&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST:/api/transactions&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;metrics&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;processing_time&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5000.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;risk_score&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.02&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;h4&gt;
  
  
  SaaS Platform Health
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Track feature usage patterns
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_business_metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;feature_adoption&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.95&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_metric&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;service&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user-service&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;endpoint&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GET:/api/users&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;metrics&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;response_time&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cache_hit_rate&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.92&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;h3&gt;
  
  
  🚀 Performance Characteristics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Throughput&lt;/strong&gt;: 10,000+ metrics/second per collector instance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency&lt;/strong&gt;: &amp;lt;50ms for metric ingestion, &amp;lt;1s for anomaly detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Efficiency&lt;/strong&gt;: ~1GB for 1M service interactions using Count-Min Sketches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Horizontal scaling with Redis clustering support&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔧 Production Deployment
&lt;/h3&gt;

&lt;p&gt;The system includes production-ready configurations:&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="c1"&gt;# High Availability Setup&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Redis Cluster (3 nodes) - Data persistence &amp;amp; processing&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Data Collector (2+ replicas) - Load balanced ingestion&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;AI Service (1 replica) - Model training &amp;amp; detection&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Dashboard (2+ replicas) - User interface &amp;amp; API&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  💡 Key Innovations
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Probabilistic Monitoring&lt;/strong&gt;: Count-Min Sketches enable monitoring of high-frequency events without memory explosion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time AI&lt;/strong&gt;: Continuous model training and anomaly detection using Redis Streams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Latency Alerts&lt;/strong&gt;: Pub/Sub ensures instant notification of issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server-Side Processing&lt;/strong&gt;: RedisGears eliminates external aggregation overhead&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified Data Platform&lt;/strong&gt;: Single Redis instance handles all aspects of monitoring&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🌟 Why This Matters
&lt;/h3&gt;

&lt;p&gt;Traditional monitoring systems often suffer from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Alert Fatigue&lt;/strong&gt;: Too many false positives&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Silos&lt;/strong&gt;: Separate systems for logs, metrics, and alerts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Latency&lt;/strong&gt;: Batch processing delays&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Explosion&lt;/strong&gt;: Storing every single event&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This Redis-powered solution addresses all these issues by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using AI to reduce false positives by 80%&lt;/li&gt;
&lt;li&gt;Unifying all data in Redis with appropriate data structures&lt;/li&gt;
&lt;li&gt;Providing real-time processing with Redis Streams&lt;/li&gt;
&lt;li&gt;Using probabilistic structures for memory efficiency&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔮 Future Enhancements
&lt;/h3&gt;

&lt;p&gt;The architecture is designed for extensibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Model Support&lt;/strong&gt;: Different ML algorithms for different metric types&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Aggregations&lt;/strong&gt;: User-defined RedisGears scripts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regional Deployment&lt;/strong&gt;: Edge instances for global monitoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced Analytics&lt;/strong&gt;: Time-series analysis and forecasting&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📚 Getting Started
&lt;/h3&gt;

&lt;p&gt;The project includes comprehensive documentation and examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/AI-Anamoly-Detector/blob/main/INTEGRATION_GUIDE.md" rel="noopener noreferrer"&gt;Integration Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/AI-Anamoly-Detector/blob/main/REAL_WORLD_INTEGRATION.md" rel="noopener noreferrer"&gt;Real-World Examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/AI-Anamoly-Detector/tree/main/client-sdks" rel="noopener noreferrer"&gt;Client SDKs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🎉 Conclusion
&lt;/h3&gt;

&lt;p&gt;This project demonstrates how Redis 8 can be transformed from a simple cache into a powerful real-time data processing and AI platform. By leveraging Redis Streams, Count-Min Sketches, Pub/Sub, and RedisGears, we've built a production-ready anomaly detection system that scales from startups to enterprises.&lt;/p&gt;

&lt;p&gt;The key insight is that Redis isn't just for caching anymore - it's a complete data platform that can handle real-time streaming, probabilistic analytics, machine learning workflows, and instant messaging, all while maintaining the performance and reliability that made Redis famous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redis 8: Beyond the Cache, Into the Future of Real-Time AI.&lt;/strong&gt;&lt;/p&gt;




</description>
      <category>redischallenge</category>
      <category>devchallenge</category>
      <category>database</category>
      <category>ai</category>
    </item>
    <item>
      <title>Real-Time AI Dungeon Master: Multiplayer Storytelling with Redis 8 (Streams, Pub/Sub, RedisJSON)</title>
      <dc:creator>Nauman Tanwir</dc:creator>
      <pubDate>Sat, 09 Aug 2025 19:33:01 +0000</pubDate>
      <link>https://forem.com/ntanwir10/real-time-ai-dungeon-master-multiplayer-storytelling-with-redis-8-streams-pubsub-redisjson-j32</link>
      <guid>https://forem.com/ntanwir10/real-time-ai-dungeon-master-multiplayer-storytelling-with-redis-8-streams-pubsub-redisjson-j32</guid>
      <description>&lt;h2&gt;
  
  
  This is a submission for the &lt;a href="https://dev.to/challenges/redis-2025-07-23"&gt;Redis AI Challenge&lt;/a&gt;: Real-Time AI Innovators
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Real-Time AI Dungeon Master is a multiplayer, AI-driven storytelling game that uses Redis as its real-time data layer to synchronize sessions, broadcast narrative updates, and persist game history.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI Dungeon Master&lt;/strong&gt;: Narrative powered by OpenAI GPT with contextual prompts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiplayer in real time&lt;/strong&gt;: Players join a shared session and collaborate via WebSocket (Socket.IO)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis-first architecture&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Sessions: &lt;code&gt;HSET game:{sessionId}:state&lt;/code&gt; (status, created_at, last_activity)&lt;/li&gt;
&lt;li&gt;Event log: &lt;code&gt;XADD game:{sessionId}:events&lt;/code&gt; (immutable history and replay)&lt;/li&gt;
&lt;li&gt;Active players: &lt;code&gt;SADD game:{sessionId}:players&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Broadcasts: &lt;code&gt;PUBLISH game:{sessionId}:updates&lt;/code&gt; → Socket.IO &lt;code&gt;game:update&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Semantic lore: &lt;code&gt;JSON.SET lore:{id}&lt;/code&gt; (embeddings + metadata)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Production-friendly&lt;/strong&gt;: Rate limiting, error handling, environment validation, health checks, graceful shutdown&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Full stack&lt;/strong&gt;: Node.js/TypeScript backend, React + Tailwind frontend, Dockerized with nginx proxy&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master" rel="noopener noreferrer"&gt;github.com/ntanwir10/realtime_ai_dungeon_master&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ntanwir10" rel="noopener noreferrer"&gt;
        ntanwir10
      &lt;/a&gt; / &lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master" rel="noopener noreferrer"&gt;
        realtime_ai_dungeon_master
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      AI-powered collaborative storytelling through real-time multiplayer adventures! Built entirely around Redis as the high-performance real-time data layer, this project pushes the boundaries of interactive AI gaming.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🐍 Real-Time AI Dungeon Master - Redis AI Challenge Submission&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;🚀 &lt;strong&gt;AI-powered collaborative storytelling through real-time multiplayer adventures!&lt;/strong&gt; Built entirely around &lt;strong&gt;Redis&lt;/strong&gt; as the high-performance real-time data layer, this project pushes the boundaries of interactive AI gaming.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Real-Time AI Dungeon Master&lt;/strong&gt; - The ultimate AI-powered multiplayer game, leveraging Redis for seamless real-time state management and dynamic storytelling.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Built for the &lt;a href="https://dev.to/challenges/redis-2025-07-23?" rel="nofollow"&gt;Redis AI Challenge&lt;/a&gt;&lt;/strong&gt; 🏆&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Competing in the &lt;strong&gt;"Real-Time AI Innovators"&lt;/strong&gt; challenge prompt, demonstrating how Redis accelerates the future of AI through high-impact use cases like real-time feature streaming, semantic caching, and advanced state management.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📋 Table of Contents&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#-project-overview" rel="noopener noreferrer"&gt;🎯 Project Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#features" rel="noopener noreferrer"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#architecture" rel="noopener noreferrer"&gt;Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#-semantic-lore-system" rel="noopener noreferrer"&gt;🧠 Semantic Lore System&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#prerequisites" rel="noopener noreferrer"&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#quick-start" rel="noopener noreferrer"&gt;Quick Start&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#%EF%B8%8F-service-architecture--container-details" rel="noopener noreferrer"&gt;🏗️ Service Architecture &amp;amp; Container Details&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#docker-deployment" rel="noopener noreferrer"&gt;Docker Deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#api-endpoints" rel="noopener noreferrer"&gt;API Endpoints&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#development" rel="noopener noreferrer"&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#project-structure" rel="noopener noreferrer"&gt;Project Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#redis-data-structures" rel="noopener noreferrer"&gt;Redis Data Structures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#-redis-cli-commands--data-access" rel="noopener noreferrer"&gt;🔧 Redis CLI Commands &amp;amp; Data Access&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#-real-redis-data-examples" rel="noopener noreferrer"&gt;📊 Real Redis Data Examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#-understanding-redis-data-structure" rel="noopener noreferrer"&gt;🔍 Understanding Redis Data Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#-data-analysis-insights" rel="noopener noreferrer"&gt;📈 Data Analysis Insights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master#-redis-command-summary" rel="noopener noreferrer"&gt;📋 Redis Command&lt;/a&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ntanwir10/realtime_ai_dungeon_master" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;If this isn’t live at the moment, you can run it locally in minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full walk‑through demo (screen recording):&lt;/strong&gt; Shows creating a session, joining, sending commands, and receiving AI narratives in real time.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/VWw2p_MPHgk"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Quick start with Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/ntanwir10/realtime_ai_dungeon_master
&lt;span class="nb"&gt;cd &lt;/span&gt;realtime_ai_dungeon_master
&lt;span class="nb"&gt;cp &lt;/span&gt;backend/.env.example backend/.env   &lt;span class="c"&gt;# add your OpenAI API key&lt;/span&gt;
docker-compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;span class="c"&gt;# Frontend: http://localhost:5173&lt;/span&gt;
&lt;span class="c"&gt;# Backend:  http://localhost:3001&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Manual development setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Redis JSON&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 6379:6379 redislabs/rejson:latest

&lt;span class="c"&gt;# Backend&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;backend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run dev

&lt;span class="c"&gt;# Frontend&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ../frontend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Landing Page, Session Details and Create Session&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frhxk4l8cxnefr7akoe99.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frhxk4l8cxnefr7akoe99.png" alt="Landing Page, Session Details and Create Session"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In‑Game View: Story Log after a command and Multiplayer Gameplay&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhkehhbld6bsg6vh195tj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhkehhbld6bsg6vh195tj.png" alt="Story Log with AI narrative and Multiplayer gameplay"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redis CLI: Sessions, State, Events, Players&lt;/strong&gt;&lt;br&gt;
![Redis CLI views]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;List all keys (overview)&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1ea67f6wx36w2umfi66.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1ea67f6wx36w2umfi66.png" alt="List all keys"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;List all sessions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb0d17z1jljw3caldv9v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb0d17z1jljw3caldv9v.png" alt="List all sessions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Showing multiple user sessions’ state&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faa5df986xmgj3mmxwwja.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faa5df986xmgj3mmxwwja.png" alt="multiple user sessions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Show recent events for that session (Streams)&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Show active players in that session (Sets)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlla8d8jhdecoiy62vr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlla8d8jhdecoiy62vr7.png" alt="active players in that session"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Live Pub/Sub Screen recording
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pub/Sub live updates (Redis PSUBSCRIBE + client command → narrative broadcast):
  &lt;iframe src="https://www.youtube.com/embed/GtUq3cvzXWM"&gt;
  &lt;/iframe&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Used Redis 8
&lt;/h2&gt;

&lt;p&gt;This project treats Redis as the system-of-record and real-time backbone. It uses Redis 8–8-compatible primitives plus RedisJSON for AI-centric data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Real-time event streaming (Streams)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;XADD game:{sessionId}:events&lt;/code&gt; captures every player action as an immutable event&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;XRANGE&lt;/code&gt; builds AI context and enables replay/debugging&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Low-latency state access (Hashes)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HSET game:{sessionId}:state&lt;/code&gt; stores session status and timestamps for fast reads (&lt;code&gt;HGETALL&lt;/code&gt;, &lt;code&gt;HGET&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Presence and discovery (Sets + Keys)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SADD game:{sessionId}:players&lt;/code&gt; tracks active players; &lt;code&gt;SCARD&lt;/code&gt; for presence count&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;KEYS game:*:state&lt;/code&gt; supports session discovery for the session browser&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Broadcast updates (Pub/Sub)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend publishes narrative updates to &lt;code&gt;game:{sessionId}:updates&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A Redis subscriber relays messages to Socket.IO &lt;code&gt;game:update&lt;/code&gt; for all connected clients&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Semantic lore with JSON and embeddings (RedisJSON)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lore entries are stored as JSON: &lt;code&gt;lore:{id}&lt;/code&gt; with &lt;code&gt;{ id, type, title, content, embedding, tags, created_at, updated_at }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Embeddings are generated with OpenAI and stored directly in Redis JSON&lt;/li&gt;
&lt;li&gt;Semantic similarity is computed in the app layer via cosine similarity, enabling contextual prompts&lt;/li&gt;
&lt;li&gt;Type and tag indexing via Sets: &lt;code&gt;lore:type:{type}&lt;/code&gt;, &lt;code&gt;lore:tag:{tag}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Future enhancement: swap app-layer similarity for Redis Stack vector indexes for server-side vector search&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Why Redis 8 for AI apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Streams + Pub/Sub&lt;/strong&gt; deliver real-time narrative fan-out with minimal latency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hashes/Sets&lt;/strong&gt; keep presence and session state O(1)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RedisJSON&lt;/strong&gt; stores rich, evolving AI knowledge artifacts (lore) adjacent to fast operational data&lt;/li&gt;
&lt;li&gt;The combination forms a semantic cache that reduces LLM prompt size and calls by grounding responses in structured, retrievable context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Team: Solo project.&lt;/p&gt;

&lt;p&gt;Thanks for reading! If you try it, I’d love to hear your feedback. Repo: &lt;a href="https://github.com/ntanwir10/realtime_ai_dungeon_master" rel="noopener noreferrer"&gt;github.com/ntanwir10/realtime_ai_dungeon_master&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;By submitting this entry, you agree to receive communications from Redis regarding products, services, events, and special offers. You can unsubscribe at any time. Your information will be handled in accordance with &lt;a href="https://redis.io/legal/privacy-policy/" rel="noopener noreferrer"&gt;Redis's Privacy Policy&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>redischallenge</category>
      <category>devchallenge</category>
      <category>database</category>
      <category>ai</category>
    </item>
    <item>
      <title>CodeSage - MCP-First Code Discovery</title>
      <dc:creator>Nauman Tanwir</dc:creator>
      <pubDate>Sun, 27 Jul 2025 16:01:36 +0000</pubDate>
      <link>https://forem.com/ntanwir10/codesage-mcp-first-code-discovery-322a</link>
      <guid>https://forem.com/ntanwir10/codesage-mcp-first-code-discovery-322a</guid>
      <description>&lt;h2&gt;
  
  
  Building CodeSage: A MCP-First Code Discovery Platform
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/algolia-2025-07-09"&gt;Algolia MCP Server Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CodeSage&lt;/strong&gt; is an AI-powered code discovery platform built entirely around the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;. It transforms GitHub repositories into AI-searchable knowledge bases, enabling natural language exploration of codebases through Claude Desktop and other MCP-compatible AI clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/ntanwir10/codesage-algolia-challenge" rel="noopener noreferrer"&gt;CodeSage MCP-First Code Discovery&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ntanwir10" rel="noopener noreferrer"&gt;
        ntanwir10
      &lt;/a&gt; / &lt;a href="https://github.com/ntanwir10/codesage-algolia-challenge" rel="noopener noreferrer"&gt;
        codesage-algolia-challenge
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      AI-powered code discovery through natural language - Built entirely around the Model Context Protocol (MCP) for seamless integration with Claude Desktop and other AI clients
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;CodeSage - MCP-First Code Discovery&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;🚀 &lt;strong&gt;AI-powered code discovery through natural language&lt;/strong&gt; - Built entirely around the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; for seamless integration with Claude Desktop and other AI clients.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;CodeSage - MCP-First Code Discovery&lt;/strong&gt; - The only code discovery tool built entirely around the Model Context Protocol for seamless AI integration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Built for the &lt;a href="https://dev.to/challenges/algolia-2025-07-09" rel="nofollow"&gt;Algolia MCP Server Challenge&lt;/a&gt;&lt;/strong&gt; 🏆&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Competing in the &lt;strong&gt;Backend Data Optimization&lt;/strong&gt; and &lt;strong&gt;Ultimate User Experience&lt;/strong&gt; categories with our innovative MCP-first approach to code discovery.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎯 What is CodeSage?&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;CodeSage - MCP-First Code Discovery&lt;/strong&gt; transforms GitHub repositories into &lt;strong&gt;AI-searchable knowledge bases&lt;/strong&gt; through the Model Context Protocol. Submit a repository URL, and within minutes your AI assistant can discover functions, understand architecture, and answer complex questions about the codebase through natural language - all via MCP integration.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;&lt;strong&gt;🎯 Final User Experience&lt;/strong&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;1. User submits: github.com/facebook/react
2. System processes: GitHub → Parser → Algolia
3. User opens&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ntanwir10/codesage-algolia-challenge" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Key Innovation: MCP-First Architecture
&lt;/h3&gt;

&lt;p&gt;CodeSage is the only code discovery tool built entirely around MCP standards. Unlike traditional code search tools that require direct API integration, CodeSage leverages the Model Context Protocol to provide seamless AI integration, eliminating the need for direct AI API calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  📊 Complete System Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────────────────┐
│                              CODESAGE ARCHITECTURE                          │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌─────────────┐    ┌──────────────┐    ┌─────────────┐    ┌─────────────┐ │
│  │   Frontend  │───▶│   Backend    │───▶│   Algolia   │    │   GitHub    │ │
│  │   (Simple)  │    │ (Processing) │    │  (Search)   │◀───│     API     │ │
│  └─────────────┘    └──────────────┘    └─────────────┘    └─────────────┘ │
│                              │                                             │
│                              ▼                                             │
│                     ┌──────────────┐    ┌─────────────┐                   │
│                     │     MCP      │───▶│   Claude    │                   │
│                     │   Protocol   │    │  Desktop    │                   │
│                     └──────────────┘    └─────────────┘                   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Key Architecture Flows:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository Management&lt;/strong&gt;: Frontend ↔ Backend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Discovery&lt;/strong&gt;: Claude Desktop ↔ MCP ↔ Backend ↔ Algolia&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Direct Integration&lt;/strong&gt;: Frontend never talks to Algolia or MCP&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔄 Processing Pipeline
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Repository Submission Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Input → Frontend → POST /repositories/ → Backend
    ↓
Database Record (status: pending)
    ↓
Background Processing Triggered
    ↓
GitHub API Integration
    ↓
File Parsing &amp;amp; Analysis
    ↓
Algolia Indexing
    ↓
Status Update (status: completed)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Code Discovery Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Claude Desktop User Query
    ↓
MCP Protocol Call
    ↓
POST /api/v1/ai/mcp/tools/call
    ↓
MCP Tool Execution
    ↓
Algolia Search Query
    ↓
Search Results
    ↓
Formatted Response
    ↓
Claude Desktop Display
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Core Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository Processing&lt;/strong&gt;: Automatic ingestion and parsing of GitHub repositories&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Algolia-Powered Search&lt;/strong&gt;: Fast, semantic code search with intelligent indexing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Tools&lt;/strong&gt;: Natural language code discovery through Claude Desktop&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Processing&lt;/strong&gt;: Live status updates and WebSocket integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language Support&lt;/strong&gt;: Parses functions, classes, and imports across languages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Utilized the Algolia MCP Server
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;MCP-First Architecture Design&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;CodeSage is built entirely around the Model Context Protocol, making it unique among code discovery tools. The architecture follows this flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Query → Claude Desktop → MCP Protocol → CodeSage Backend → Algolia Search → Formatted Results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Algolia Integration for Code Search&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I implemented a comprehensive Algolia service that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Indexes Code Entities&lt;/strong&gt;: Functions, classes, variables, and imports are parsed and indexed with semantic metadata&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized Search Settings&lt;/strong&gt;: Configured searchable attributes, faceting, and custom ranking for code-specific relevance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language Support&lt;/strong&gt;: Handles Python, JavaScript, TypeScript, and other languages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository Isolation&lt;/strong&gt;: Each repository gets its own search context&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;MCP Tools Implementation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I created five core MCP tools that leverage Algolia's search capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;search_code&lt;/code&gt;&lt;/strong&gt;: Natural language code search across repositories&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;analyze_repository&lt;/code&gt;&lt;/strong&gt;: Repository overview and architectural insights
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;explore_functions&lt;/code&gt;&lt;/strong&gt;: Function discovery and relationship mapping&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;explain_code&lt;/code&gt;&lt;/strong&gt;: Detailed code explanations and documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;find_patterns&lt;/code&gt;&lt;/strong&gt;: Pattern detection for security, performance, and architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Real-world Usage Example&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# User submits repository&lt;/span&gt;
POST /api/v1/repositories/
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"url"&lt;/span&gt;: &lt;span class="s2"&gt;"https://github.com/facebook/react"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# User asks Claude Desktop&lt;/span&gt;
&lt;span class="s2"&gt;"Show me React's rendering lifecycle functions"&lt;/span&gt;

&lt;span class="c"&gt;# Claude uses MCP tool&lt;/span&gt;
POST /api/v1/ai/mcp/tools/call
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"tool_name"&lt;/span&gt;: &lt;span class="s2"&gt;"search_code"&lt;/span&gt;,
  &lt;span class="s2"&gt;"arguments"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"query"&lt;/span&gt;: &lt;span class="s2"&gt;"rendering lifecycle"&lt;/span&gt;,
    &lt;span class="s2"&gt;"repository"&lt;/span&gt;: &lt;span class="s2"&gt;"react"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Algolia returns relevant functions&lt;/span&gt;
&lt;span class="c"&gt;# Claude provides AI-powered analysis&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. &lt;strong&gt;MCP Tools Available&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;search_code&lt;/code&gt;&lt;/strong&gt; - Natural language code search across repositories&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;analyze_repository&lt;/code&gt;&lt;/strong&gt; - Repository overview and architectural insights&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;explore_functions&lt;/code&gt;&lt;/strong&gt; - Function discovery and relationship mapping&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;explain_code&lt;/code&gt;&lt;/strong&gt; - Detailed code explanations and documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;find_patterns&lt;/code&gt;&lt;/strong&gt; - Pattern detection for security, performance, architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Technical Implementation&lt;/strong&gt;
&lt;/h3&gt;

&lt;h2&gt;
  
  
  🏗 System Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Backend (FastAPI)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Location&lt;/strong&gt;: &lt;code&gt;backend/app/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core Services&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;repository_service.py&lt;/code&gt; - Repository CRUD and processing logic&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mcp_server.py&lt;/code&gt; - MCP protocol implementation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ai_service.py&lt;/code&gt; - MCP tools implementation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;algolia_service.py&lt;/code&gt; - Search indexing and querying&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;security_service.py&lt;/code&gt; - Rate limiting and validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Database Models&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Repository&lt;/code&gt; - Repository metadata and status&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CodeFile&lt;/code&gt; - Individual file records&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CodeEntity&lt;/code&gt; - Functions, classes, imports extracted from files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;API Endpoints&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Repository Management
&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;    &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;repositories&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;        &lt;span class="c1"&gt;# List repositories
&lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;   &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;repositories&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;        &lt;span class="c1"&gt;# Create repository  
&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;    &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;repositories&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;    &lt;span class="c1"&gt;# Get repository
&lt;/span&gt;&lt;span class="n"&gt;DELETE&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;repositories&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;    &lt;span class="c1"&gt;# Delete repository
&lt;/span&gt;
&lt;span class="c1"&gt;# MCP Protocol
&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;    &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ai&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;capabilities&lt;/span&gt;     &lt;span class="c1"&gt;# MCP server capabilities
&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;    &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ai&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;           &lt;span class="c1"&gt;# List MCP tools
&lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;   &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ai&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;/&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;call&lt;/span&gt;      &lt;span class="c1"&gt;# Execute MCP tool
&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;    &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ai&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;mcp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;  &lt;span class="c1"&gt;# Read MCP resource
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Frontend (React + TypeScript)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Location&lt;/strong&gt;: &lt;code&gt;frontend/src/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Simple repository management interface&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repository submission form&lt;/li&gt;
&lt;li&gt;Repository list with status&lt;/li&gt;
&lt;li&gt;Basic CRUD operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No complex search UI&lt;/strong&gt; - AI discovery happens through Claude Desktop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Components&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repository form with GitHub URL validation&lt;/li&gt;
&lt;li&gt;Real-time status tracking via WebSocket&lt;/li&gt;
&lt;li&gt;Modern UI with TailwindCSS&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Backend Stack:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI for MCP server implementation&lt;/li&gt;
&lt;li&gt;SQLAlchemy for data persistence&lt;/li&gt;
&lt;li&gt;Algolia for search indexing and querying&lt;/li&gt;
&lt;li&gt;WebSocket for real-time status updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Frontend Stack:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React 18 with TypeScript&lt;/li&gt;
&lt;li&gt;TailwindCSS for modern UI&lt;/li&gt;
&lt;li&gt;Real-time status tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;MCP Integration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom MCP server implementation&lt;/li&gt;
&lt;li&gt;Tool-based architecture for extensibility&lt;/li&gt;
&lt;li&gt;Resource-based data access patterns&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  Development Process
&lt;/h3&gt;

&lt;p&gt;Building CodeSage taught me several valuable lessons about MCP-first architecture:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;MCP Standards Matter&lt;/strong&gt;: Building around MCP from the ground up creates a more flexible and extensible system than retrofitting existing tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Design is Critical&lt;/strong&gt;: Well-designed MCP tools can provide powerful AI capabilities without requiring direct AI API integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search Integration is Key&lt;/strong&gt;: Algolia's semantic search capabilities perfectly complement MCP's natural language interface&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Challenges Faced
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;MCP Protocol Complexity&lt;/strong&gt;: Understanding and implementing the Model Context Protocol required a deep dive into the specification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search Optimization&lt;/strong&gt;: Configuring Algolia for code-specific search patterns required extensive testing and tuning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Processing&lt;/strong&gt;: Implementing background processing with status updates required careful WebSocket integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling&lt;/strong&gt;: MCP tools need robust error handling to provide meaningful feedback to AI clients&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What I Learned
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;MCP-First Design&lt;/strong&gt;: Building around MCP standards from the start creates more AI-friendly applications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search Architecture&lt;/strong&gt;: Algolia's faceting and filtering capabilities are perfect for code discovery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Abstraction&lt;/strong&gt;: Well-designed MCP tools can abstract complex operations into simple natural language interfaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Optimization&lt;/strong&gt;: Code search requires careful indexing strategies and query optimization&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Technical Innovations
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;MCP-First Code Discovery&lt;/strong&gt;: The only code discovery tool built entirely around MCP standards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Algolia-MCP Integration&lt;/strong&gt;: Seamless integration between Algolia's search capabilities and MCP's tool system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural Language Code Exploration&lt;/strong&gt;: Users can ask complex questions about codebases through Claude Desktop&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository Processing Pipeline&lt;/strong&gt;: Automated ingestion, parsing, and indexing of GitHub repositories&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Future Possibilities
&lt;/h3&gt;

&lt;p&gt;CodeSage demonstrates the potential for MCP-first applications in various domains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentation Discovery&lt;/strong&gt;: Similar approach for technical documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Exploration&lt;/strong&gt;: Natural language API discovery and testing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Analysis&lt;/strong&gt;: AI-powered security pattern detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Review&lt;/strong&gt;: Automated code review through MCP tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The combination of Algolia's powerful search capabilities with MCP's natural language interface opens up exciting possibilities for AI-powered development tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Impact
&lt;/h2&gt;

&lt;p&gt;CodeSage represents a fundamental shift in how developers interact with codebases. As the first MCP-first code discovery platform, it demonstrates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI-Native Design&lt;/strong&gt;: Building around MCP standards creates more powerful AI integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural Language Future&lt;/strong&gt;: Developers can ask complex questions about codebases in plain English&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search + AI Synergy&lt;/strong&gt;: Algolia's semantic search combined with MCP's natural language interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project has broader implications for the AI tool ecosystem, showing how to build applications that work seamlessly with Claude Desktop and other MCP clients. The architecture can be applied to documentation discovery, API exploration, security analysis, and knowledge management.&lt;/p&gt;

&lt;p&gt;CodeSage proves that MCP-first applications can revolutionize how we interact with complex data through natural language, opening new possibilities for AI-powered development tools.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Thanks for participating!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;p&gt;This project represents a new paradigm in AI-powered development tools, one where the Model Context Protocol enables seamless integration between powerful search engines, such as Algolia, and AI assistants, like Claude Desktop.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>algoliachallenge</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Deploying FastAPI to AWS: Part 3 - Going Serverless with Lambda</title>
      <dc:creator>Nauman Tanwir</dc:creator>
      <pubDate>Sun, 13 Jul 2025 18:22:06 +0000</pubDate>
      <link>https://forem.com/ntanwir10/deploying-fastapi-to-aws-part-3-going-serverless-with-lambda-2aj8</link>
      <guid>https://forem.com/ntanwir10/deploying-fastapi-to-aws-part-3-going-serverless-with-lambda-2aj8</guid>
      <description>&lt;p&gt;&lt;em&gt;This is Part 3 of our FastAPI deployment series. We've covered EC2 and ECS Fargate - now let's explore the serverless approach.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;After deploying my FastAPI journal API using &lt;a href="https://dev.tolink-to-part-1"&gt;EC2&lt;/a&gt; and &lt;a href="https://dev.tolink-to-part-2"&gt;ECS Fargate&lt;/a&gt;, I started working on some side projects. The problem? Even the smallest ECS setup was costing me $30-50/month per project, and most of my side projects get maybe 100 requests per day.&lt;/p&gt;

&lt;p&gt;That's when I discovered Lambda could run the same FastAPI application for literally $1-2 per month. Here's how serverless changed my approach to deploying personal projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Serverless Makes Sense
&lt;/h2&gt;

&lt;p&gt;Lambda isn't always the answer, but it's perfect when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Variable traffic&lt;/strong&gt;: Some days 10 requests, some days 1000&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost is a concern&lt;/strong&gt;: You want to pay only for what you use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal maintenance&lt;/strong&gt;: You don't want to manage any infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quick experiments&lt;/strong&gt;: You want to deploy and test ideas fast&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For my journal API side project, Lambda was perfect because I'm the only user most days, but occasionally I share it with friends for feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Serverless Architecture
&lt;/h2&gt;

&lt;p&gt;Here's what we're building:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Internet → API Gateway → Lambda Functions → RDS Proxy → RDS PostgreSQL
                                    ↓
                            CloudWatch Logs (automatic)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pay-per-request pricing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic scaling&lt;/strong&gt; (0 to thousands of requests)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No server management&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built-in monitoring&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Adapting FastAPI for Lambda
&lt;/h2&gt;

&lt;p&gt;Lambda doesn't run web servers like uvicorn. Instead, it processes events. We need an adapter to make FastAPI work with Lambda events.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Mangum
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;mangum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Modify Your FastAPI App
&lt;/h3&gt;

&lt;p&gt;Create a new file &lt;code&gt;lambda_handler.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mangum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Mangum&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.main&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;

&lt;span class="c1"&gt;# Disable lifespan events for Lambda
&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lifespan_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="c1"&gt;# Create the Lambda handler
&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Mangum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lifespan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;off&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update Your FastAPI App
&lt;/h3&gt;

&lt;p&gt;Make some Lambda-friendly changes to your main app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In app/main.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;contextlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asynccontextmanager&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="c1"&gt;# Check if running in Lambda
&lt;/span&gt;&lt;span class="n"&gt;IS_LAMBDA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;AWS_LAMBDA_FUNCTION_NAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="nd"&gt;@asynccontextmanager&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Startup
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;IS_LAMBDA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Only run startup tasks when not in Lambda
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Starting up...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt;
    &lt;span class="c1"&gt;# Shutdown
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;IS_LAMBDA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Shutting down...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create app with conditional lifespan
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;IS_LAMBDA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Journal API&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Journal API&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lifespan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Your existing routes...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handle Database Connections
&lt;/h3&gt;

&lt;p&gt;Lambda functions are stateless, so we need to handle database connections carefully:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In your database connection file
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_engine&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy.pool&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NullPool&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_database_url&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;AWS_LAMBDA_FUNCTION_NAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Use RDS Proxy for Lambda
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgresql://&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rds_proxy_endpoint&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:5432/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Direct connection for local development
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgresql://&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;rds_endpoint&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:5432/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Create engine with appropriate pooling
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;AWS_LAMBDA_FUNCTION_NAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# No connection pooling for Lambda
&lt;/span&gt;    &lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get_database_url&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;poolclass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;NullPool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Normal pooling for non-Lambda environments
&lt;/span&gt;    &lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;get_database_url&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Set Up RDS Proxy
&lt;/h2&gt;

&lt;p&gt;Lambda functions can overwhelm your database with connections. RDS Proxy solves this by managing connection pooling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create RDS Proxy
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# First, create a secret for database credentials&lt;/span&gt;
aws secretsmanager create-secret &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; journal-db-credentials &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Database credentials for journal API"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--secret-string&lt;/span&gt; &lt;span class="s1"&gt;'{"username":"postgres","password":"YourSecurePassword123"}'&lt;/span&gt;

&lt;span class="c"&gt;# Create RDS Proxy&lt;/span&gt;
aws rds create-db-proxy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--db-proxy-name&lt;/span&gt; journal-db-proxy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--engine-family&lt;/span&gt; POSTGRESQL &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--auth&lt;/span&gt; &lt;span class="s1"&gt;'{
        "AuthScheme": "SECRETS",
        "SecretArn": "arn:aws:secretsmanager:us-east-1:account:secret:journal-db-credentials",
        "IAMAuth": "DISABLED"
    }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role-arn&lt;/span&gt; arn:aws:iam::account:role/RDSProxyRole &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--vpc-subnet-ids&lt;/span&gt; subnet-xxxxxxxxx subnet-yyyyyyyyy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--vpc-security-group-ids&lt;/span&gt; sg-xxxxxxxxx

&lt;span class="c"&gt;# Register RDS instance with proxy&lt;/span&gt;
aws rds register-db-proxy-targets &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--db-proxy-name&lt;/span&gt; journal-db-proxy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--db-instance-identifiers&lt;/span&gt; journal-db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Package and Deploy with SAM
&lt;/h2&gt;

&lt;p&gt;AWS SAM makes Lambda deployment much easier. Create a &lt;code&gt;template.yaml&lt;/code&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;AWSTemplateFormatVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2010-09-09'&lt;/span&gt;
&lt;span class="na"&gt;Transform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Serverless-2016-10-31&lt;/span&gt;

&lt;span class="na"&gt;Globals&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Function&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
    &lt;span class="na"&gt;MemorySize&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;512&lt;/span&gt;
    &lt;span class="na"&gt;Runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3.11&lt;/span&gt;

&lt;span class="na"&gt;Parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;DatabaseHost&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;String&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RDS Proxy endpoint&lt;/span&gt;

&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;JournalApiFunction&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;AWS::Serverless::Function&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;CodeUri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;Handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lambda_handler.handler&lt;/span&gt;
      &lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;Variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;DatabaseHost&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5432&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;journal_db&lt;/span&gt;
      &lt;span class="na"&gt;Events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;ApiGateway&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;Api&lt;/span&gt;
          &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/{proxy+}&lt;/span&gt;
            &lt;span class="na"&gt;Method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ANY&lt;/span&gt;
        &lt;span class="na"&gt;ApiGatewayRoot&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;Api&lt;/span&gt;
          &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
            &lt;span class="na"&gt;Method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ANY&lt;/span&gt;
      &lt;span class="na"&gt;VpcConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;SecurityGroupIds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sg-xxxxxxxxx&lt;/span&gt;
        &lt;span class="na"&gt;SubnetIds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;subnet-xxxxxxxxx&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;subnet-yyyyyyyyy&lt;/span&gt;

  &lt;span class="c1"&gt;# IAM role for Lambda&lt;/span&gt;
  &lt;span class="na"&gt;JournalApiRole&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;AWS::IAM::Role&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;AssumeRolePolicyDocument&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2012-10-17'&lt;/span&gt;
        &lt;span class="na"&gt;Statement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow&lt;/span&gt;
            &lt;span class="na"&gt;Principal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;Service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lambda.amazonaws.com&lt;/span&gt;
            &lt;span class="na"&gt;Action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sts:AssumeRole&lt;/span&gt;
      &lt;span class="na"&gt;ManagedPolicyArns&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole&lt;/span&gt;
      &lt;span class="na"&gt;Policies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;PolicyName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SecretsManagerAccess&lt;/span&gt;
          &lt;span class="na"&gt;PolicyDocument&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;Version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2012-10-17'&lt;/span&gt;
            &lt;span class="na"&gt;Statement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Effect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow&lt;/span&gt;
                &lt;span class="na"&gt;Action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;secretsmanager:GetSecretValue&lt;/span&gt;
                &lt;span class="na"&gt;Resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
                  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;arn:aws:secretsmanager:*:*:secret:journal-db-credentials*&lt;/span&gt;

&lt;span class="na"&gt;Outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ApiGatewayUrl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;API&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Gateway&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;endpoint&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;URL"&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Sub&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy with SAM
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build the application&lt;/span&gt;
sam build

&lt;span class="c"&gt;# Deploy&lt;/span&gt;
sam deploy &lt;span class="nt"&gt;--guided&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The guided deployment will ask for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stack name: &lt;code&gt;journal-api-lambda&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;AWS Region: &lt;code&gt;us-east-1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Database host: Your RDS Proxy endpoint&lt;/li&gt;
&lt;li&gt;Confirm changes before deploy: &lt;code&gt;Y&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Handle Database Migrations
&lt;/h2&gt;

&lt;p&gt;Lambda functions are ephemeral, so we need a different approach for migrations. Create a separate Lambda function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# migration_handler.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Run Alembic migrations in Lambda&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Set database URL from environment
&lt;/span&gt;        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgresql://&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POSTGRES_HOST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:5432/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

        &lt;span class="c1"&gt;# Run migrations
&lt;/span&gt;        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;alembic&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;upgrade&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;head&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
                              &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Migrations completed successfully: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Migration failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Error running migrations: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this to your SAM template:&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;MigrationFunction&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;AWS::Serverless::Function&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;CodeUri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;Handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;migration_handler.handler&lt;/span&gt;
      &lt;span class="na"&gt;Timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;
      &lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;Variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;DatabaseHost&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5432&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;journal_db&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Testing and Monitoring
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Test Your Lambda Function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get your API Gateway URL from SAM output&lt;/span&gt;
curl https://your-api-id.execute-api.us-east-1.amazonaws.com/Prod/health

&lt;span class="c"&gt;# Test authentication&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://your-api-id.execute-api.us-east-1.amazonaws.com/Prod/auth/signup &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"email": "test@example.com", "password": "testpass123"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Monitor Performance
&lt;/h3&gt;

&lt;p&gt;Lambda automatically sends metrics to CloudWatch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# View function metrics&lt;/span&gt;
aws logs describe-log-groups &lt;span class="nt"&gt;--log-group-name-prefix&lt;/span&gt; /aws/lambda/journal-api

&lt;span class="c"&gt;# View recent logs&lt;/span&gt;
aws logs &lt;span class="nb"&gt;tail&lt;/span&gt; /aws/lambda/journal-api-JournalApiFunction-XXXXXXXXX &lt;span class="nt"&gt;--follow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Optimize for Production
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Handle Cold Starts
&lt;/h3&gt;

&lt;p&gt;Cold starts can add 1-3 seconds to the first request. Here are some optimizations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In lambda_handler.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mangum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Mangum&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.main&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize outside the handler for reuse
&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Mangum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lifespan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;off&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Warm-up function
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Handle ALB health checks
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;httpMethod&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;event&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;path&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/health&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;healthy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Handle normal requests
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use Provisioned Concurrency
&lt;/h3&gt;

&lt;p&gt;For critical endpoints, you can eliminate cold starts:&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="c1"&gt;# Add to your SAM template&lt;/span&gt;
  &lt;span class="na"&gt;JournalApiFunction&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;AWS::Serverless::Function&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# ... other properties&lt;/span&gt;
      &lt;span class="na"&gt;ProvisionedConcurrencyConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;ProvisionedConcurrencyLevel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Optimize Package Size
&lt;/h3&gt;

&lt;p&gt;Keep your deployment package small for faster cold starts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create requirements-lambda.txt with only production dependencies&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--target&lt;/span&gt; ./package &lt;span class="nt"&gt;-r&lt;/span&gt; requirements-lambda.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Performance and Costs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Performance Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;EC2&lt;/th&gt;
&lt;th&gt;ECS Fargate&lt;/th&gt;
&lt;th&gt;Lambda&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cold Start&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;30-60s&lt;/td&gt;
&lt;td&gt;1-3s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warm Response&lt;/td&gt;
&lt;td&gt;50-100ms&lt;/td&gt;
&lt;td&gt;50-100ms&lt;/td&gt;
&lt;td&gt;50-100ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling Time&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;1-2 minutes&lt;/td&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max Concurrent&lt;/td&gt;
&lt;td&gt;Instance limit&lt;/td&gt;
&lt;td&gt;Task limit&lt;/td&gt;
&lt;td&gt;1000+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Cost Comparison (for my side project)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Monthly usage: ~10,000 requests, mostly during weekdays&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EC2 (t3.micro)&lt;/strong&gt;: $8.50 + RDS = ~$25/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ECS Fargate&lt;/strong&gt;: $15-30 + RDS = ~$35-50/month
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda&lt;/strong&gt;: $0.20 + API Gateway $0.35 + RDS = ~$15/month&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For low-traffic applications, Lambda is significantly cheaper.&lt;/p&gt;

&lt;h2&gt;
  
  
  When NOT to Use Lambda
&lt;/h2&gt;

&lt;p&gt;Lambda isn't perfect for everything:&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoid Lambda When:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Long-running processes&lt;/strong&gt;: 15-minute execution limit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large file processing&lt;/strong&gt;: Memory and storage limitations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent high traffic&lt;/strong&gt;: Costs can exceed container solutions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex state management&lt;/strong&gt;: Stateless nature can be limiting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time applications&lt;/strong&gt;: Cold starts affect user experience&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Stick with ECS/EC2 When:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You need persistent connections (WebSockets)&lt;/li&gt;
&lt;li&gt;Processing large files or datasets&lt;/li&gt;
&lt;li&gt;Running background jobs longer than 15 minutes&lt;/li&gt;
&lt;li&gt;Consistent traffic patterns make containers more cost-effective&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Good
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Incredible cost savings&lt;/strong&gt; for variable workloads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero infrastructure management&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic scaling&lt;/strong&gt; handles any traffic spike&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in monitoring&lt;/strong&gt; and logging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast deployment&lt;/strong&gt; and iteration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Challenges
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cold starts&lt;/strong&gt; can surprise users&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;15-minute timeout&lt;/strong&gt; limits some use cases&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPC configuration&lt;/strong&gt; can be tricky&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database connection management&lt;/strong&gt; requires RDS Proxy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging&lt;/strong&gt; is different from traditional applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Series Wrap-Up: Which Approach Should You Choose?
&lt;/h2&gt;

&lt;p&gt;After deploying the same FastAPI application three different ways, here's my recommendation framework:&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose EC2 When:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🎓 Learning cloud fundamentals&lt;/li&gt;
&lt;li&gt;🔧 Need specific OS configurations&lt;/li&gt;
&lt;li&gt;💰 Predictable, steady traffic patterns&lt;/li&gt;
&lt;li&gt;🏢 Legacy application requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Choose ECS Fargate When:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🚀 Building production applications&lt;/li&gt;
&lt;li&gt;📈 Need automatic scaling and high availability&lt;/li&gt;
&lt;li&gt;👥 Working with a team on modern DevOps practices&lt;/li&gt;
&lt;li&gt;🛡️ Require enterprise-grade reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Choose Lambda When:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;💸 Cost optimization is critical&lt;/li&gt;
&lt;li&gt;⚡ Building MVPs or side projects&lt;/li&gt;
&lt;li&gt;📊 Traffic is highly variable or unpredictable&lt;/li&gt;
&lt;li&gt;🎯 Want zero infrastructure management&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Current Setup Strategy
&lt;/h2&gt;

&lt;p&gt;For new projects, I now follow this pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with Lambda&lt;/strong&gt; for MVPs and experiments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move to ECS Fargate&lt;/strong&gt; when traffic becomes consistent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consider EC2&lt;/strong&gt; only for special requirements&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach minimizes costs during development and scales appropriately as projects grow.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What's your experience with serverless FastAPI applications? Have you tried Lambda, or are you using other serverless platforms?&lt;/strong&gt; Share your thoughts and questions in the comments!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If this series helped you, please share it with other developers who might be facing similar deployment decisions.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This concludes our 3-part series on deploying FastAPI to AWS. Check out the other parts:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://dev.to/ntanwir10/deploying-fastapi-to-aws-part-1-the-ec2-approach-learning-the-fundamentals-2889"&gt;Part 1 - The EC2 Approach&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="https://dev.to/ntanwir10/deploying-fastapi-to-aws-part-2-containerizing-with-ecs-fargate-5hlh"&gt;Part 2 - Containerizing with ECS Fargate&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  fastapi #aws #lambda #serverless #python #webdev #devops #tutorial #beginners
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>serverless</category>
      <category>fastapi</category>
    </item>
    <item>
      <title>Deploying FastAPI to AWS: Part 2 - Containerizing with ECS Fargate</title>
      <dc:creator>Nauman Tanwir</dc:creator>
      <pubDate>Sun, 13 Jul 2025 18:18:18 +0000</pubDate>
      <link>https://forem.com/ntanwir10/deploying-fastapi-to-aws-part-2-containerizing-with-ecs-fargate-5hlh</link>
      <guid>https://forem.com/ntanwir10/deploying-fastapi-to-aws-part-2-containerizing-with-ecs-fargate-5hlh</guid>
      <description>&lt;p&gt;This is Part 2 of a 3-part series. In Part 1, we deployed FastAPI using EC2. Now let's see how containers change the game.*&lt;/p&gt;




&lt;p&gt;After deploying my FastAPI journal API using EC2 (covered in &lt;a href="https://dev.to/ntanwir10/deploying-fastapi-to-aws-part-1-the-ec2-approach-learning-the-fundamentals-2889"&gt;Part 1&lt;/a&gt;, I started running into some operational challenges. Manual scaling, server maintenance, and the "it works on my machine" problem made me realize why so many teams are moving to containers.&lt;/p&gt;

&lt;p&gt;In this part, we'll take the same FastAPI application and deploy it using ECS Fargate with RDS. You'll see how this approach solves many of the challenges we faced with EC2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Containers Changed Everything for Me
&lt;/h2&gt;

&lt;p&gt;After a few weeks of managing EC2 instances manually, I experienced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My app crashed during a traffic spike (no auto-scaling)&lt;/li&gt;
&lt;li&gt;A deployment broke production (environment differences)&lt;/li&gt;
&lt;li&gt;Spending weekends doing server maintenance&lt;/li&gt;
&lt;li&gt;Debugging issues that only happened in production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Containers solved all of these problems. Here's how.&lt;/p&gt;

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

&lt;p&gt;Same FastAPI journal API, but now with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Internet → Application Load Balancer → ECS Fargate Tasks → RDS PostgreSQL
                                              ↓
                                      CloudWatch Logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This architecture gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic scaling&lt;/strong&gt; based on traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High availability&lt;/strong&gt; across multiple zones&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy deployments&lt;/strong&gt; with zero downtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent environments&lt;/strong&gt; from dev to production&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Containerizing the FastAPI Application
&lt;/h2&gt;

&lt;p&gt;First, let's create a Dockerfile for our journal API:&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; python:3.11-slim&lt;/span&gt;

&lt;span class="c"&gt;# Set working directory&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Install system dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    gcc &lt;span class="se"&gt;\
&lt;/span&gt;    curl &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="c"&gt;# Copy requirements and install Python dependencies&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Copy application code&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Create non-root user for security&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;useradd &lt;span class="nt"&gt;--create-home&lt;/span&gt; &lt;span class="nt"&gt;--shell&lt;/span&gt; /bin/bash app &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; app:app /app
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; app&lt;/span&gt;

&lt;span class="c"&gt;# Expose port&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8000&lt;/span&gt;

&lt;span class="c"&gt;# Health check for ECS&lt;/span&gt;
&lt;span class="k"&gt;HEALTHCHECK&lt;/span&gt;&lt;span class="s"&gt; --interval=30s --timeout=30s --start-period=5s --retries=3 \&lt;/span&gt;
    CMD curl -f http://localhost:8000/health || exit 1

&lt;span class="c"&gt;# Run the application&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add a Health Check Endpoint
&lt;/h3&gt;

&lt;p&gt;ECS needs a way to check if your container is healthy. Add this to your FastAPI app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In your main.py or create a new health.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;APIRouter&lt;/span&gt;

&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@router.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/health&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;health_check&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;healthy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Add to your main app
&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test Locally
&lt;/h3&gt;

&lt;p&gt;Before deploying, make sure your container works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build the image&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; journal-api &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Run locally&lt;/span&gt;
docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8000:8000 &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env journal-api

&lt;span class="c"&gt;# Test it&lt;/span&gt;
curl http://localhost:8000/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Set Up AWS Infrastructure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create ECR Repository
&lt;/h3&gt;

&lt;p&gt;We need a place to store our Docker images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create ECR repository&lt;/span&gt;
aws ecr create-repository &lt;span class="nt"&gt;--repository-name&lt;/span&gt; journal-api

&lt;span class="c"&gt;# Get login token and login&lt;/span&gt;
aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 | docker login &lt;span class="nt"&gt;--username&lt;/span&gt; AWS &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; your-account-id.dkr.ecr.us-east-1.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Push Your Image
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Tag your image&lt;/span&gt;
docker tag journal-api:latest your-account-id.dkr.ecr.us-east-1.amazonaws.com/journal-api:latest

&lt;span class="c"&gt;# Push to ECR&lt;/span&gt;
docker push your-account-id.dkr.ecr.us-east-1.amazonaws.com/journal-api:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create RDS Database
&lt;/h3&gt;

&lt;p&gt;Instead of managing PostgreSQL ourselves, let's use RDS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create DB subnet group&lt;/span&gt;
aws rds create-db-subnet-group &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--db-subnet-group-name&lt;/span&gt; journal-db-subnet-group &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--db-subnet-group-description&lt;/span&gt; &lt;span class="s2"&gt;"Subnet group for journal database"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--subnet-ids&lt;/span&gt; subnet-xxxxxxxxx subnet-yyyyyyyyy

&lt;span class="c"&gt;# Create RDS instance&lt;/span&gt;
aws rds create-db-instance &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--db-instance-identifier&lt;/span&gt; journal-db &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--db-instance-class&lt;/span&gt; db.t3.micro &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--engine&lt;/span&gt; postgres &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--engine-version&lt;/span&gt; 15.4 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--master-username&lt;/span&gt; postgres &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--master-user-password&lt;/span&gt; YourSecurePassword123 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--allocated-storage&lt;/span&gt; 20 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--vpc-security-group-ids&lt;/span&gt; sg-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--db-subnet-group-name&lt;/span&gt; journal-db-subnet-group &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--backup-retention-period&lt;/span&gt; 7 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--multi-az&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Create ECS Cluster
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecs create-cluster &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; journal-api-cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create Task Definition
&lt;/h3&gt;

&lt;p&gt;This is where we define how our container should run:&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;"family"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"journal-api-task"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"networkMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awsvpc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requiresCompatibilities"&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="s2"&gt;"FARGATE"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cpu"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"256"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"memory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"512"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"executionRoleArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::your-account:role/ecsTaskExecutionRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"taskRoleArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::your-account:role/ecsTaskRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"containerDefinitions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"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;"journal-api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-account-id.dkr.ecr.us-east-1.amazonaws.com/journal-api:latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"portMappings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"containerPort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tcp"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"essential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"logConfiguration"&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;"logDriver"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awslogs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"options"&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;"awslogs-group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/ecs/journal-api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"awslogs-region"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"awslogs-stream-prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ecs"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"environment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"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;"POSTGRES_HOST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-rds-endpoint.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="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;"POSTGRES_PORT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5432"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"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;"POSTGRES_DB"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"journal_db"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"secrets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"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;"POSTGRES_USER"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"valueFrom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:secretsmanager:us-east-1:account:secret:db-user"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"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;"POSTGRES_PASSWORD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"valueFrom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:secretsmanager:us-east-1:account:secret:db-password"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"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;"SECRET_KEY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"valueFrom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:secretsmanager:us-east-1:account:secret:jwt-secret"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"healthCheck"&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;"command"&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="s2"&gt;"CMD-SHELL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"curl -f http://localhost:8000/health || exit 1"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"interval"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"retries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"startPeriod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register the task definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecs register-task-definition &lt;span class="nt"&gt;--cli-input-json&lt;/span&gt; file://task-definition.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Set Up Application Load Balancer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create Application Load Balancer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create ALB&lt;/span&gt;
aws elbv2 create-load-balancer &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; journal-api-alb &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--subnets&lt;/span&gt; subnet-xxxxxxxxx subnet-yyyyyyyyy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--security-groups&lt;/span&gt; sg-xxxxxxxxx

&lt;span class="c"&gt;# Create target group&lt;/span&gt;
aws elbv2 create-target-group &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; journal-api-targets &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--protocol&lt;/span&gt; HTTP &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--port&lt;/span&gt; 8000 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; vpc-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--target-type&lt;/span&gt; ip &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--health-check-path&lt;/span&gt; /health &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--health-check-interval-seconds&lt;/span&gt; 30 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--healthy-threshold-count&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--unhealthy-threshold-count&lt;/span&gt; 3

&lt;span class="c"&gt;# Create listener&lt;/span&gt;
aws elbv2 create-listener &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--load-balancer-arn&lt;/span&gt; arn:aws:elasticloadbalancing:... &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--protocol&lt;/span&gt; HTTP &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--port&lt;/span&gt; 80 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--default-actions&lt;/span&gt; &lt;span class="nv"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;forward,TargetGroupArn&lt;span class="o"&gt;=&lt;/span&gt;arn:aws:elasticloadbalancing:...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Create ECS Service with Auto Scaling
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create the Service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecs create-service &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cluster&lt;/span&gt; journal-api-cluster &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--service-name&lt;/span&gt; journal-api-service &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--task-definition&lt;/span&gt; journal-api-task:1 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--desired-count&lt;/span&gt; 2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--launch-type&lt;/span&gt; FARGATE &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network-configuration&lt;/span&gt; &lt;span class="s2"&gt;"awsvpcConfiguration={subnets=[subnet-xxxxxxxxx,subnet-yyyyyyyyy],securityGroups=[sg-xxxxxxxxx],assignPublicIp=ENABLED}"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--load-balancers&lt;/span&gt; &lt;span class="nv"&gt;targetGroupArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arn:aws:elasticloadbalancing:...,containerName&lt;span class="o"&gt;=&lt;/span&gt;journal-api,containerPort&lt;span class="o"&gt;=&lt;/span&gt;8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Up Auto Scaling
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Register scalable target&lt;/span&gt;
aws application-autoscaling register-scalable-target &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--service-namespace&lt;/span&gt; ecs &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-id&lt;/span&gt; service/journal-api-cluster/journal-api-service &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--scalable-dimension&lt;/span&gt; ecs:service:DesiredCount &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--min-capacity&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--max-capacity&lt;/span&gt; 10

&lt;span class="c"&gt;# Create scaling policy&lt;/span&gt;
aws application-autoscaling put-scaling-policy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--service-namespace&lt;/span&gt; ecs &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--resource-id&lt;/span&gt; service/journal-api-cluster/journal-api-service &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--scalable-dimension&lt;/span&gt; ecs:service:DesiredCount &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--policy-name&lt;/span&gt; journal-api-scaling-policy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--policy-type&lt;/span&gt; TargetTrackingScaling &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--target-tracking-scaling-policy-configuration&lt;/span&gt; &lt;span class="s1"&gt;'{
        "TargetValue": 70.0,
        "PredefinedMetricSpecification": {
            "PredefinedMetricType": "ECSServiceAverageCPUUtilization"
        },
        "ScaleOutCooldown": 300,
        "ScaleInCooldown": 300
    }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Database Migration and Testing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Run Database Migrations
&lt;/h3&gt;

&lt;p&gt;You can run migrations as a one-time ECS task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create migration task definition (similar to main task but with migration command)&lt;/span&gt;
&lt;span class="c"&gt;# Then run it:&lt;/span&gt;
aws ecs run-task &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cluster&lt;/span&gt; journal-api-cluster &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--task-definition&lt;/span&gt; journal-api-migration:1 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--launch-type&lt;/span&gt; FARGATE &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--network-configuration&lt;/span&gt; &lt;span class="s2"&gt;"awsvpcConfiguration={subnets=[subnet-xxxxxxxxx],securityGroups=[sg-xxxxxxxxx],assignPublicIp=ENABLED}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test Your Deployment
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get your load balancer DNS name&lt;/span&gt;
aws elbv2 describe-load-balancers &lt;span class="nt"&gt;--names&lt;/span&gt; journal-api-alb

&lt;span class="c"&gt;# Test the API&lt;/span&gt;
curl http://your-alb-dns-name.us-east-1.elb.amazonaws.com/health
curl http://your-alb-dns-name.us-east-1.elb.amazonaws.com/docs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I Learned: ECS vs EC2
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Good
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto-scaling actually works&lt;/strong&gt;: Traffic spikes don't crash your app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-downtime deployments&lt;/strong&gt;: Rolling updates happen automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent environments&lt;/strong&gt;: Same container runs everywhere&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better monitoring&lt;/strong&gt;: CloudWatch integration is built-in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Less maintenance&lt;/strong&gt;: No OS updates or server management&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Challenges
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learning curve&lt;/strong&gt;: Understanding containers, task definitions, and ECS concepts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging&lt;/strong&gt;: Can't SSH into containers (but logs are better organized)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt;: Slightly higher than EC2 for consistent workloads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt;: More moving parts than simple EC2 setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cost Comparison
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EC2&lt;/strong&gt;: ~$25-50/month (predictable)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ECS Fargate&lt;/strong&gt;: ~$30-80/month (scales with usage)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Production Tips
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Use Secrets Manager
&lt;/h3&gt;

&lt;p&gt;Never put sensitive data in environment variables:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;secretsmanager&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_secret_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SecretId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;secret_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SecretString&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Set Up Proper Logging
&lt;/h3&gt;



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

&lt;span class="c1"&gt;# Structured logging for CloudWatch
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JSONFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Formatter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;log_entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;formatTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;level&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;levelname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;module&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Configure logging
&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StreamHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setFormatter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JSONFormatter&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&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="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Health Checks Matter
&lt;/h3&gt;

&lt;p&gt;Make your health check meaningful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/health&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;health_check&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Check database connection
&lt;/span&gt;        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT 1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;healthy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;connected&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;503&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Database connection failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Gotchas
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Memory limits&lt;/strong&gt;: Set them appropriately or containers get killed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task definitions are immutable&lt;/strong&gt;: You create new revisions, not edit existing ones&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security groups&lt;/strong&gt;: ALB and ECS tasks need different security group rules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs&lt;/strong&gt;: They go to CloudWatch, not local files&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;In Part 3, we'll explore the serverless approach with AWS Lambda. You'll see when it makes sense to go completely serverless and how to adapt your FastAPI application for Lambda.&lt;/p&gt;

&lt;p&gt;We'll also compare all three approaches and help you decide which one fits your specific use case.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;How has your experience been with containers? Are you using ECS, or have you tried other orchestration platforms?&lt;/strong&gt; Share your thoughts in the comments!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't miss Part 3 - follow me to get notified when it's published!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Coming next: &lt;a href="https://dev.tolink-to-part-3"&gt;Part 3 - Going Serverless with Lambda&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Previous: &lt;a href="https://dev.to/ntanwir10/deploying-fastapi-to-aws-part-1-the-ec2-approach-learning-the-fundamentals-2889"&gt;Part 1 - The EC2 Approach&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  fastapi #aws #docker #containers #ecs #devops #python #webdev #tutorial
&lt;/h1&gt;

</description>
      <category>ecs</category>
      <category>fargate</category>
      <category>fastapi</category>
      <category>aws</category>
    </item>
    <item>
      <title>Deploying FastAPI to AWS: Part 1 - The EC2 Approach (Learning the Fundamentals)</title>
      <dc:creator>Nauman Tanwir</dc:creator>
      <pubDate>Sun, 13 Jul 2025 18:14:13 +0000</pubDate>
      <link>https://forem.com/ntanwir10/deploying-fastapi-to-aws-part-1-the-ec2-approach-learning-the-fundamentals-2889</link>
      <guid>https://forem.com/ntanwir10/deploying-fastapi-to-aws-part-1-the-ec2-approach-learning-the-fundamentals-2889</guid>
      <description>&lt;p&gt;&lt;em&gt;This is Part 1 of a 3-part series on deploying FastAPI applications to AWS. We'll start with EC2 to understand the fundamentals.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I just finished building my first real FastAPI application - a journal API with JWT authentication, PostgreSQL database, and all the features you'd expect. The app worked perfectly on my laptop, but then I hit the wall that every developer faces: &lt;strong&gt;how do I deploy this thing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After trying different approaches and making plenty of mistakes, I decided to document what I learned. This series will cover three main ways to deploy FastAPI to AWS, starting with the most educational approach: EC2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Start with EC2?
&lt;/h2&gt;

&lt;p&gt;I know what you're thinking - "Isn't EC2 old school? Shouldn't I use containers or serverless?" &lt;/p&gt;

&lt;p&gt;Here's the thing: starting with EC2 taught me networking, security, and infrastructure concepts that I use every day now. It's like learning to drive with a manual transmission - once you understand the fundamentals, everything else makes more sense.&lt;/p&gt;

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

&lt;p&gt;Our FastAPI application has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User authentication with JWT tokens&lt;/li&gt;
&lt;li&gt;PostgreSQL database&lt;/li&gt;
&lt;li&gt;Email functionality for password resets&lt;/li&gt;
&lt;li&gt;RESTful endpoints for journal entries&lt;/li&gt;
&lt;li&gt;Environment-based configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to deploy this securely on AWS with proper networking and database separation.&lt;/p&gt;

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

&lt;p&gt;We'll create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Internet Gateway → Public Subnet (FastAPI VM) → Private Subnet (PostgreSQL VM)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup teaches you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPC networking concepts&lt;/li&gt;
&lt;li&gt;Security group configuration&lt;/li&gt;
&lt;li&gt;Database security best practices&lt;/li&gt;
&lt;li&gt;Server management fundamentals&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Setting Up the Network Infrastructure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create the VPC
&lt;/h3&gt;

&lt;p&gt;First, let's create our Virtual Private Cloud:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create VPC&lt;/span&gt;
aws ec2 create-vpc &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cidr-block&lt;/span&gt; 10.0.0.0/16 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=vpc,Tags=[{Key=Name,Value=journal-api-vpc}]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create Subnets
&lt;/h3&gt;

&lt;p&gt;We need a public subnet for our API server and a private subnet for the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Public subnet for API server&lt;/span&gt;
aws ec2 create-subnet &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; vpc-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cidr-block&lt;/span&gt; 10.0.1.0/24 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--availability-zone&lt;/span&gt; us-east-1a &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=subnet,Tags=[{Key=Name,Value=public-subnet}]'&lt;/span&gt;

&lt;span class="c"&gt;# Private subnet for database&lt;/span&gt;
aws ec2 create-subnet &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; vpc-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cidr-block&lt;/span&gt; 10.0.2.0/24 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--availability-zone&lt;/span&gt; us-east-1a &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=subnet,Tags=[{Key=Name,Value=private-subnet}]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Internet Gateway and Routing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create and attach an internet gateway&lt;/span&gt;
aws ec2 create-internet-gateway &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=internet-gateway,Tags=[{Key=Name,Value=journal-igw}]'&lt;/span&gt;

aws ec2 attach-internet-gateway &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; vpc-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--internet-gateway-id&lt;/span&gt; igw-xxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Security Groups (This Is Important!)
&lt;/h2&gt;

&lt;p&gt;Security groups are like firewalls for your instances. Getting this right is crucial for security.&lt;/p&gt;

&lt;h3&gt;
  
  
  API Server Security Group
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a security group for the API server&lt;/span&gt;
aws ec2 create-security-group &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--group-name&lt;/span&gt; journal-api-sg &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Security group for FastAPI server"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; vpc-xxxxxxxxx

&lt;span class="c"&gt;# Allow HTTP traffic on port 8000&lt;/span&gt;
aws ec2 authorize-security-group-ingress &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--group-id&lt;/span&gt; sg-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--protocol&lt;/span&gt; tcp &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--port&lt;/span&gt; 8000 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cidr&lt;/span&gt; 0.0.0.0/0

&lt;span class="c"&gt;# Allow SSH for management&lt;/span&gt;
aws ec2 authorize-security-group-ingress &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--group-id&lt;/span&gt; sg-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--protocol&lt;/span&gt; tcp &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--port&lt;/span&gt; 22 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cidr&lt;/span&gt; 0.0.0.0/0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Database Security Group
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a security group for the database&lt;/span&gt;
aws ec2 create-security-group &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--group-name&lt;/span&gt; journal-db-sg &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Security group for PostgreSQL"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; vpc-xxxxxxxxx

&lt;span class="c"&gt;# Allow PostgreSQL access ONLY from the API server&lt;/span&gt;
aws ec2 authorize-security-group-ingress &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--group-id&lt;/span&gt; sg-yyyyyyyyy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--protocol&lt;/span&gt; tcp &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--port&lt;/span&gt; 5432 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--source-group&lt;/span&gt; sg-xxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Point&lt;/strong&gt;: Notice how the database only accepts connections from the API server security group, not from the entire internet. This is a fundamental security practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Launch the Instances
&lt;/h2&gt;

&lt;h3&gt;
  
  
  API Server Instance
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 run-instances &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--image-id&lt;/span&gt; ami-0c02fb55956c7d316 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--instance-type&lt;/span&gt; t3.micro &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--key-name&lt;/span&gt; your-key-pair &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--security-group-ids&lt;/span&gt; sg-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; subnet-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--associate-public-ip-address&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=instance,Tags=[{Key=Name,Value=journal-api-server}]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Database Instance
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 run-instances &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--image-id&lt;/span&gt; ami-0c02fb55956c7d316 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--instance-type&lt;/span&gt; t3.micro &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--key-name&lt;/span&gt; your-key-pair &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--security-group-ids&lt;/span&gt; sg-yyyyyyyyy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--subnet-id&lt;/span&gt; subnet-yyyyyyyyy &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tag-specifications&lt;/span&gt; &lt;span class="s1"&gt;'ResourceType=instance,Tags=[{Key=Name,Value=journal-db-server}]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Setting Up the API Server
&lt;/h2&gt;

&lt;p&gt;SSH into your API server and let's get FastAPI running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update the system&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Install Python 3.11&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;software-properties-common &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;add-apt-repository ppa:deadsnakes/ppa &lt;span class="nt"&gt;-y&lt;/span&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;python3.11 python3.11-venv python3.11-dev python3-pip git &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Clone your repository (replace with your repo)&lt;/span&gt;
git clone https://github.com/your-username/journal-api.git
&lt;span class="nb"&gt;cd &lt;/span&gt;journal-api

&lt;span class="c"&gt;# Create virtual environment&lt;/span&gt;
python3.11 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Environment Configuration
&lt;/h3&gt;

&lt;p&gt;Create your &lt;code&gt;.env&lt;/code&gt; file with the database connection:&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;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .env &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
POSTGRES_HOST=10.0.2.xxx  # Private IP of your database server
POSTGRES_PORT=5432
POSTGRES_USER=journal_user
POSTGRES_PASSWORD=your_secure_password
POSTGRES_DB=journal_db
SECRET_KEY=your_jwt_secret_key
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_DAYS=7
EMAIL_SENDER=your_email@example.com
EMAIL_PASSWORD=your_app_password
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Database Setup
&lt;/h2&gt;

&lt;p&gt;Now let's set up PostgreSQL on the database server. You'll need to access it through a bastion host or AWS Systems Manager Session Manager since it's in a private subnet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install PostgreSQL&lt;/span&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;postgresql postgresql-contrib &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Start and enable PostgreSQL&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start postgresql
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;postgresql

&lt;span class="c"&gt;# Create a database and a user&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; postgres psql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the PostgreSQL prompt:&lt;br&gt;
&lt;/p&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;journal_db&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;USER&lt;/span&gt; &lt;span class="n"&gt;journal_user&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;PASSWORD&lt;/span&gt; &lt;span class="s1"&gt;'your_secure_password'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="k"&gt;PRIVILEGES&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;journal_db&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="n"&gt;journal_user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure PostgreSQL for Remote Access
&lt;/h3&gt;

&lt;p&gt;Edit the configuration files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Edit postgresql.conf&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/postgresql/15/main/postgresql.conf
&lt;span class="c"&gt;# Change: listen_addresses = '*'&lt;/span&gt;

&lt;span class="c"&gt;# Edit pg_hba.conf&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/postgresql/15/main/pg_hba.conf
&lt;span class="c"&gt;# Add: host    all    all    10.0.1.0/24    md5&lt;/span&gt;

&lt;span class="c"&gt;# Restart PostgreSQL&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Deploy and Test
&lt;/h2&gt;

&lt;p&gt;Back on your API server, run the database migrations:&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;journal-api
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
alembic upgrade &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start your FastAPI application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvicorn app.main:app &lt;span class="nt"&gt;--host&lt;/span&gt; 0.0.0.0 &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://your-public-ip:8000/docs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Making It Production Ready
&lt;/h2&gt;

&lt;p&gt;For a production setup, create a systemd service:&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 tee&lt;/span&gt; /etc/systemd/system/journal-api.service &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
[Unit]
Description=Journal API FastAPI application
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/journal-api
Environment=PATH=/home/ubuntu/journal-api/venv/bin
ExecStart=/home/ubuntu/journal-api/venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000
Restart=always

[Install]
WantedBy=multi-user.target
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;journal-api
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start journal-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Good:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete control over the environment&lt;/li&gt;
&lt;li&gt;Great for understanding networking and security&lt;/li&gt;
&lt;li&gt;Predictable costs&lt;/li&gt;
&lt;li&gt;Easy to debug with direct SSH access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Challenges:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manual scaling (you handle load balancing yourself)&lt;/li&gt;
&lt;li&gt;Ongoing maintenance (OS updates, security patches)&lt;/li&gt;
&lt;li&gt;Single points of failure&lt;/li&gt;
&lt;li&gt;More operational overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; Around $25-50/month for a small application&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Opening security groups too wide&lt;/strong&gt; - Only allow the minimum required access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not setting up monitoring&lt;/strong&gt; - At least enable CloudWatch basic monitoring&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forgetting backups&lt;/strong&gt; - Set up automated database backups&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not using Elastic IP&lt;/strong&gt; - Your public IP will change when you restart the instance&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;In Part 2, we'll look at containerizing this same application and deploying it with ECS Fargate. You'll see how containers solve many of the operational challenges we faced with EC2.&lt;/p&gt;

&lt;p&gt;In Part 3, we'll explore the serverless approach with Lambda and see when it makes sense to go completely serverless.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Have you tried deploying FastAPI to EC2? What challenges did you face?&lt;/strong&gt; Drop your questions in the comments - I'll answer them and might include solutions in the next parts of this series.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Found this helpful? Follow me for Parts 2 and 3 of this series!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Next up: &lt;a href="https://dev.to/ntanwir10/deploying-fastapi-to-aws-part-2-containerizing-with-ecs-fargate-5hlh"&gt;Part 2 - Containerizing with ECS Fargate&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  fastapi #aws #python #webdev #devops #beginners #tutorial #ec2
&lt;/h1&gt;

</description>
      <category>fastapi</category>
      <category>aws</category>
      <category>python</category>
      <category>ec2</category>
    </item>
  </channel>
</rss>
