<?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: Ahmed Adel</title>
    <description>The latest articles on Forem by Ahmed Adel (@ahmedadel).</description>
    <link>https://forem.com/ahmedadel</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%2F688023%2F6df3b916-a7ca-4b9d-a775-f3aa7c88c5d8.png</url>
      <title>Forem: Ahmed Adel</title>
      <link>https://forem.com/ahmedadel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ahmedadel"/>
    <language>en</language>
    <item>
      <title>Amazon Nova 2: AWS's Reasoning Models That Actually Get Production Needs!</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Sun, 28 Dec 2025 15:13:11 +0000</pubDate>
      <link>https://forem.com/ahmedadel/amazon-nova-2-awss-reasoning-models-that-actually-get-production-needs-2ad0</link>
      <guid>https://forem.com/ahmedadel/amazon-nova-2-awss-reasoning-models-that-actually-get-production-needs-2ad0</guid>
      <description>&lt;h1&gt;
  
  
  🚀 Amazon Nova 2: AWS's Reasoning Models That Actually &lt;em&gt;Get&lt;/em&gt; Production Needs!
&lt;/h1&gt;

&lt;p&gt;Hey devs! 😎 Ever built an AI agent that overthinks pizza orders but chokes on complex workflows? Amazon Nova 2 fixes that with &lt;strong&gt;adaptive reasoning&lt;/strong&gt;—think more on hard problems, less on easy ones. Launched Dec 2025, these Bedrock models bring &lt;strong&gt;1M-token context&lt;/strong&gt;, multimodal magic (text+images+video+speech), and &lt;strong&gt;thinking budgets&lt;/strong&gt; you control.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Why Nova 2 Feels Like Cheating
&lt;/h2&gt;

&lt;p&gt;Nova 2 Lite &amp;amp; Pro solve the classic AI tradeoff: speed vs intelligence. &lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;🎛️ &lt;strong&gt;Thinking Budgets&lt;/strong&gt;: Low/Medium/High—dial reasoning depth to match task complexity&lt;/li&gt;
&lt;li&gt;🛠️ &lt;strong&gt;Built-in Tools&lt;/strong&gt;: Web grounding, code interpreter, GitHub MCP server integration&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;1M Token Context&lt;/strong&gt;: Long-range planning without forgetting&lt;/li&gt;
&lt;li&gt;🔒 &lt;strong&gt;Safety First&lt;/strong&gt;: Content moderation, Bedrock Guardrails, IP indemnity&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"Nova 2 Lite outperforms Nova Premiere on agentic workflows at &lt;strong&gt;7x lower cost&lt;/strong&gt; and &lt;strong&gt;5x faster&lt;/strong&gt;"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  📊 The Full Nova 2 Family Breakdown
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Modalities&lt;/th&gt;
&lt;th&gt;Price-Perf Edge&lt;/th&gt;
&lt;th&gt;🌟 Standout&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nova 2 Lite&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GA ✅&lt;/td&gt;
&lt;td&gt;Code gen, search, daily tasks&lt;/td&gt;
&lt;td&gt;1M tokens&lt;/td&gt;
&lt;td&gt;Text+Image+Video&lt;/td&gt;
&lt;td&gt;7x cheaper than Premiere&lt;/td&gt;
&lt;td&gt;Adaptive budgets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nova 2 Pro&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Preview 🔓&lt;/td&gt;
&lt;td&gt;Agentic coding, complex planning&lt;/td&gt;
&lt;td&gt;1M tokens&lt;/td&gt;
&lt;td&gt;Text+Image+Video+Speech&lt;/td&gt;
&lt;td&gt;SOTA math/tool use&lt;/td&gt;
&lt;td&gt;Multi-step orchestration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nova Sonic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GA ✅&lt;/td&gt;
&lt;td&gt;Real-time voice agents&lt;/td&gt;
&lt;td&gt;300k tokens&lt;/td&gt;
&lt;td&gt;Speech (5+ langs)&lt;/td&gt;
&lt;td&gt;Human-like convos&lt;/td&gt;
&lt;td&gt;Low-latency dialog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multimodal Embeddings&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GA ✅&lt;/td&gt;
&lt;td&gt;Agentic RAG/search&lt;/td&gt;
&lt;td&gt;Unified space&lt;/td&gt;
&lt;td&gt;Text+Image+Video+Audio&lt;/td&gt;
&lt;td&gt;Single model for all&lt;/td&gt;
&lt;td&gt;Cross-modal retrieval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Nova Act&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Research Preview 🔬&lt;/td&gt;
&lt;td&gt;Browser automation&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Web UI&lt;/td&gt;
&lt;td&gt;Clicks+forms+search&lt;/td&gt;
&lt;td&gt;Autonomous web agents&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  💼 Real-World Wins That'll Blow Your Mind
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;LangChain Repo Update&lt;/strong&gt; (Live Demo!) 🎥 

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



&lt;/h3&gt;

&lt;p&gt;Nova 2 Pro agent analyzed GitHub issues, created branches, read existing code, implemented changes, tested, and submitted a production-ready PR—all autonomously using GitHub MCP server integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow breakdown:&lt;/strong&gt;&lt;br&gt;
Analyze issue → Plan solution&lt;/p&gt;

&lt;p&gt;Create working branch&lt;/p&gt;

&lt;p&gt;Analyze code structure&lt;/p&gt;

&lt;p&gt;Implement Nova 2 support&lt;/p&gt;

&lt;p&gt;Test + Create PR ✅&lt;/p&gt;


&lt;h3&gt;
  
  
  2. &lt;strong&gt;Production Case Studies&lt;/strong&gt; 🏢
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Company&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Nova Model&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fortinet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Support chatbot&lt;/td&gt;
&lt;td&gt;Nova Micro&lt;/td&gt;
&lt;td&gt;Efficient doc access, reduced inference costs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infosys&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Document extraction&lt;/td&gt;
&lt;td&gt;Nova Pro&lt;/td&gt;
&lt;td&gt;Text+images → structured data extraction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Loka&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Video surveillance&lt;/td&gt;
&lt;td&gt;Nova Pro&lt;/td&gt;
&lt;td&gt;Analyzed millions of visual events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Accenture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Personalization&lt;/td&gt;
&lt;td&gt;Nova + Agents&lt;/td&gt;
&lt;td&gt;Content personalization at scale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Brand compliance&lt;/td&gt;
&lt;td&gt;Nova models&lt;/td&gt;
&lt;td&gt;Real-time decisions across 20 docs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  🧠 Thinking Budgets: The Secret Sauce
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Simple tasks&lt;/strong&gt; ⚡ &lt;em&gt;Reasoning OFF&lt;/em&gt;&lt;br&gt;
User: "Summarize these 5 URLs"&lt;br&gt;
Nova 2: Parallel web search → Instant summary &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complex agents&lt;/strong&gt; 🧠 &lt;em&gt;Reasoning HIGH&lt;/em&gt;&lt;br&gt;
User: "Update LangChain for Nova 2"&lt;br&gt;
Nova 2: Plan → Multiple tool calls → Execute → Test → PR&lt;br&gt;
​___&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip&lt;/strong&gt;: Chat apps = reasoning OFF. Multi-step agents = reasoning ON with appropriate budget.&lt;/p&gt;
&lt;h2&gt;
  
  
  🔧 Developer Quickstart
&lt;/h2&gt;

&lt;p&gt;Access via Amazon Bedrock API&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST https://bedrock-runtime.us-east-1.amazonaws.com/models/nova-2-lite
-d '{
"prompt": "Plan LangChain Nova 2 integration",
"thinking_budget": "high",
"tools": ["web_search", "code_interpreter", "github_mcp"]
}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Thinking budget&lt;/strong&gt;: "off|low|medium|high".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: Built-in web grounding, code interpreter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework&lt;/strong&gt;: Strands (agent workflows) + Agent Core (runtime)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🌍 Language &amp;amp; Fine-tuning Power
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Languages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;200+ supported, optimized for 15 (English, Arabic, Chinese, Hindi, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fine-tuning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Text + vision fine-tuning on proprietary data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Customization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Brand-specific outputs, domain adaptation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  💰 Cost Breakdown (Why You'll Love It)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task Type&lt;/th&gt;
&lt;th&gt;Old Approach&lt;/th&gt;
&lt;th&gt;Nova 2 Approach&lt;/th&gt;
&lt;th&gt;Savings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Simple Q&amp;amp;A&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Expensive overthinking&lt;/td&gt;
&lt;td&gt;Reasoning OFF&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7x cheaper&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent workflows&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slow + costly&lt;/td&gt;
&lt;td&gt;Adaptive budgets&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multimodal RAG&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multiple specialized models&lt;/td&gt;
&lt;td&gt;Single embeddings model&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Simplified stack&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  🚀 Get Started NOW
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Free Tier&lt;/strong&gt;: &lt;a href="https://go.aws/free" rel="noopener noreferrer"&gt;aws.amazon.com/bedrock/free&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;: Nova 2 User Guide&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Console&lt;/strong&gt;: Bedrock → Nova models → Test playground&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frameworks&lt;/strong&gt;: Strands + Agent Core for production agents&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🎯 Who Should Build With Nova 2?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DevOps&lt;/strong&gt; 👨‍💻: CI/CD automation, infrastructure agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fullstack&lt;/strong&gt; 🌐: Chat + RAG + tool-calling apps
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data teams&lt;/strong&gt; 📊: Multimodal search/extraction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ML engineers&lt;/strong&gt; 🔬: Production fine-tuning at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nova 2 delivers production-ready intelligence that scales without breaking the bank.&lt;/strong&gt; Who's spinning up their first agent today? Drop your builds below! 👇🚀 &lt;/p&gt;

</description>
      <category>cloud</category>
      <category>ai</category>
      <category>aws</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Architecting Large-Scale Migrations with Fannie Mae and the NRO (AWS re:Invent 2025 – WPS201)</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Sat, 13 Dec 2025 13:48:37 +0000</pubDate>
      <link>https://forem.com/ahmedadel/architecting-large-scale-migrations-with-fannie-mae-and-the-nro-aws-reinvent-2025-wps201-5582</link>
      <guid>https://forem.com/ahmedadel/architecting-large-scale-migrations-with-fannie-mae-and-the-nro-aws-reinvent-2025-wps201-5582</guid>
      <description>&lt;p&gt;&lt;strong&gt;Session:&lt;/strong&gt; WPS201 - AWS re:Invent 2025&lt;/p&gt;

&lt;p&gt;This comprehensive session explores how to migrate complex enterprise and federal workloads to AWS without disrupting critical missions or compromising security controls. The presentation combines &lt;strong&gt;core migration patterns&lt;/strong&gt;, &lt;strong&gt;AWS Well-Architected guidance&lt;/strong&gt;, and real-world customer journeys from the &lt;strong&gt;National Reconnaissance Office (NRO)&lt;/strong&gt; and &lt;strong&gt;Fannie Mae&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;

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


&lt;/p&gt;

&lt;h2&gt;
  
  
  Why large migrations are hard
&lt;/h2&gt;

&lt;p&gt;The session opens by revisiting familiar migration drivers: &lt;strong&gt;lowering compute costs&lt;/strong&gt; and &lt;strong&gt;increasing innovation velocity&lt;/strong&gt; as organizations move from on-premises environments to rehosted, replatformed, and cloud-native architectures.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 7 Rs of Migration
&lt;/h3&gt;

&lt;p&gt;The speaker frames migration strategy in terms of the "7 Rs," emphasizing that large-scale programs almost always use a &lt;strong&gt;mix&lt;/strong&gt; of these approaches rather than a single pattern:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rehost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;"Lift and shift" to cloud&lt;/td&gt;
&lt;td&gt;Quick migration, minimal changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relocate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Move to different infrastructure&lt;/td&gt;
&lt;td&gt;Hypervisor-level migrations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Repurchase&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Move to SaaS solutions&lt;/td&gt;
&lt;td&gt;Replacing custom applications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Retain&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Keep on-premises&lt;/td&gt;
&lt;td&gt;Compliance or latency requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Retire&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Eliminate unused applications&lt;/td&gt;
&lt;td&gt;Reducing technical debt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Replatform&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Minor cloud optimizations&lt;/td&gt;
&lt;td&gt;Moderate benefits with low risk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Refactor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Redesign for cloud-native&lt;/td&gt;
&lt;td&gt;Maximum cloud benefits&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Key Message:&lt;/strong&gt; Tooling alone is not enough, especially when dealing with diverse legacy systems, complex databases, and tight budgets. Organizations with limited cloud experience must invest early in &lt;strong&gt;automation&lt;/strong&gt;, &lt;strong&gt;governance&lt;/strong&gt;, and &lt;strong&gt;repeatable mechanisms&lt;/strong&gt; for account management.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Foundational patterns: MRA, phases, and landing zones
&lt;/h2&gt;

&lt;p&gt;The session recommends using an &lt;strong&gt;AWS Migration Readiness Assessment (MRA)&lt;/strong&gt; as an on-ramp for any large program. The MRA process helps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inventory applications&lt;/strong&gt; and discover dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Determine appropriate migration strategies&lt;/strong&gt; per workload&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoid one-off, unstructured decisions&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Migration Phases and Tools
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;th&gt;Key AWS Tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Assess&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Discovery &amp;amp; planning&lt;/td&gt;
&lt;td&gt;Application Discovery Service, Migration Readiness Assessment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobilize&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Setup &amp;amp; preparation&lt;/td&gt;
&lt;td&gt;Control Tower, Landing Zone, Account vending&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Migrate/Modernize&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Execution &amp;amp; optimization&lt;/td&gt;
&lt;td&gt;Migration tools, Well-Architected reviews&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In parallel, organizations should establish an &lt;strong&gt;AWS Control Tower-style landing zone&lt;/strong&gt; or "account vending machine" to provision new accounts quickly and consistently, with built-in guardrails for security, compliance, and governance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applying the AWS Well-Architected Framework
&lt;/h2&gt;

&lt;p&gt;Throughout the session, the &lt;strong&gt;AWS Well-Architected Framework&lt;/strong&gt; acts as the backbone for design and review. The six pillars are positioned as a way to reason about trade-offs for each workload, &lt;strong&gt;not as a checklist&lt;/strong&gt; to satisfy after migration.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS Well-Architected Framework Pillars
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pillar&lt;/th&gt;
&lt;th&gt;Focus Area&lt;/th&gt;
&lt;th&gt;Key Considerations&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Operational Excellence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Running &amp;amp; monitoring systems&lt;/td&gt;
&lt;td&gt;Automation, procedures, continuous improvement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Protecting information &amp;amp; systems&lt;/td&gt;
&lt;td&gt;Identity, permissions, data protection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reliability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;System availability &amp;amp; recovery&lt;/td&gt;
&lt;td&gt;Fault tolerance, backup, disaster recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance Efficiency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Using resources effectively&lt;/td&gt;
&lt;td&gt;Right-sizing, monitoring, technology selection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost Optimization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Delivering value at lowest cost&lt;/td&gt;
&lt;td&gt;Resource optimization, pricing models&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sustainability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Minimizing environmental impact&lt;/td&gt;
&lt;td&gt;Efficiency improvements, renewable energy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Practical Tip:&lt;/strong&gt; Ask business stakeholders which pillars matter most for each application. Some workloads may emphasize reliability and operational excellence, while others prioritize cost or performance. These decisions should drive architecture choices, capacity planning, and operational runbooks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Organizational enabler: a Cloud Center of Excellence
&lt;/h2&gt;

&lt;p&gt;A recurring theme is the importance of a &lt;strong&gt;Cloud Center of Excellence (CCoE)&lt;/strong&gt; for sustained modernization. The CCoE is described as a cross-functional team spanning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🏗️ &lt;strong&gt;Cloud architecture&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🖥️ &lt;strong&gt;Infrastructure&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🔒 &lt;strong&gt;Security&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;⚙️ &lt;strong&gt;Operations&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;strong&gt;Software engineering&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CCoE Responsibilities
&lt;/h3&gt;

&lt;p&gt;Rather than a purely formal committee, the CCoE serves as a &lt;strong&gt;pragmatic mechanism&lt;/strong&gt; for scaling expertise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Standardizing&lt;/strong&gt; landing zones and network patterns&lt;/li&gt;
&lt;li&gt;🔐 &lt;strong&gt;Defining&lt;/strong&gt; IAM controls and security policies&lt;/li&gt;
&lt;li&gt;💰 &lt;strong&gt;Establishing&lt;/strong&gt; cost management practices&lt;/li&gt;
&lt;li&gt;📚 &lt;strong&gt;Codifying&lt;/strong&gt; best practices and lessons learned&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Enabling&lt;/strong&gt; innovation across business units&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both &lt;strong&gt;Fannie Mae&lt;/strong&gt; and the &lt;strong&gt;NRO&lt;/strong&gt; leveraged CCoEs to significantly increase their "innovation velocity" after completing initial migrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fannie Mae: reimagining financial forecasting
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🏦 Fannie Mae Case Study: Financial Forecasting Transformation
&lt;/h2&gt;

&lt;p&gt;The Fannie Mae story focuses on transforming a &lt;strong&gt;decades-old financial forecasting process&lt;/strong&gt; into a modern, scalable platform on AWS. As a cornerstone of the U.S. housing finance system, Fannie Mae:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🏠 &lt;strong&gt;Purchases&lt;/strong&gt; home loans from lenders&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;Packages&lt;/strong&gt; them into mortgage-backed securities &lt;/li&gt;
&lt;li&gt;💼 &lt;strong&gt;Sells&lt;/strong&gt; them to investors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes accurate, timely forecasting of portfolio performance a &lt;strong&gt;mission-critical capability&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Legacy System Challenges
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Challenge&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Spreadsheet-heavy processes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual errors, limited scalability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fragmented systems&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data silos, integration complexity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;End-of-life infrastructure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Performance bottlenecks, maintenance costs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Spread-thin expertise&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Knowledge silos, single points of failure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Heavy customizations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slow change cycles, brittle systems&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These limitations severely constrained the organization's ability to provide &lt;strong&gt;forward-looking insights&lt;/strong&gt; in a dynamic macroeconomic environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ambitious goals: from 80 days to 10 days
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🎯 Program Objectives: Transforming at Scale
&lt;/h3&gt;

&lt;p&gt;Launched in &lt;strong&gt;September 2023&lt;/strong&gt;, the Forecast Transformation Program set ambitious goals:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Forecasting lifecycle&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~80 days&lt;/td&gt;
&lt;td&gt;~10 days&lt;/td&gt;
&lt;td&gt;87.5% reduction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stress-test execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sequential&lt;/td&gt;
&lt;td&gt;Parallel&lt;/td&gt;
&lt;td&gt;Concurrent processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;System consolidation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~80 systems&lt;/td&gt;
&lt;td&gt;1 platform&lt;/td&gt;
&lt;td&gt;98.75% reduction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Calculations consolidated&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~2,000&lt;/td&gt;
&lt;td&gt;Unified&lt;/td&gt;
&lt;td&gt;Single source of truth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Loan records capacity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;1.5B per run&lt;/td&gt;
&lt;td&gt;Massive scale&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Additional Requirements
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;⚡ &lt;strong&gt;Auto-scaling&lt;/strong&gt; compute based on demand&lt;/li&gt;
&lt;li&gt;🔒 &lt;strong&gt;Strict regulatory compliance&lt;/strong&gt; (security, auditability, data quality)&lt;/li&gt;
&lt;li&gt;🎭 &lt;strong&gt;Holistic approach&lt;/strong&gt; - tackling people, process, technology, and governance simultaneously&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Target architecture: S3 backbone, EMR, and Step Functions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🏗️ Solution Architecture
&lt;/h3&gt;

&lt;p&gt;Fannie Mae selected AWS for its &lt;strong&gt;comprehensive storage and database services&lt;/strong&gt; and ability to meet &lt;strong&gt;stringent security and compliance requirements&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;AWS Service&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Key Benefits&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Backbone&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Amazon S3&lt;/td&gt;
&lt;td&gt;Unified data domain&lt;/td&gt;
&lt;td&gt;Input data, model outputs, calculation results, analytics data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compute Engine&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Amazon EMR&lt;/td&gt;
&lt;td&gt;Big data processing&lt;/td&gt;
&lt;td&gt;Billions of loan records, multiple clusters, auto-scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Orchestration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AWS Step Functions&lt;/td&gt;
&lt;td&gt;End-to-end workflow&lt;/td&gt;
&lt;td&gt;Data ingestion, models, calculations, system integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Metadata &amp;amp; Config&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Aurora + DynamoDB&lt;/td&gt;
&lt;td&gt;Configuration management&lt;/td&gt;
&lt;td&gt;Scenarios, model parameters, calculation rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;User Interface&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Angular on Fargate&lt;/td&gt;
&lt;td&gt;Business user experience&lt;/td&gt;
&lt;td&gt;Scenario definition, input specification, execution triggers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Analytics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SageMaker + Tableau&lt;/td&gt;
&lt;td&gt;Reporting &amp;amp; analysis&lt;/td&gt;
&lt;td&gt;Regulatory reporting, internal analytics&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  💡 Smart Design Choice: YAML Business Logic
&lt;/h4&gt;

&lt;p&gt;A particularly clever design encodes &lt;strong&gt;business calculations in YAML&lt;/strong&gt;, which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Decouples&lt;/strong&gt; business logic from application code&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Enables&lt;/strong&gt; business-driven changes without code redeployment&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Reduces&lt;/strong&gt; development cycle time for rule updates&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Execution flow: from user input to analytics
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔄 Execution Flow: From Input to Analytics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TD
    A[Business User Input] --&amp;gt; B[Data Ingestion]
    B --&amp;gt; C[S3 Data Backbone]
    C --&amp;gt; D[Model Execution]
    D --&amp;gt; E[EMR Calculations]
    E --&amp;gt; F[Output Processing]
    F --&amp;gt; G[Analytics &amp;amp; Reporting]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step-by-Step Process
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;👤 &lt;strong&gt;User Input&lt;/strong&gt;: Business users select scenario types and enter assumptions via UI&lt;/li&gt;
&lt;li&gt;📥 &lt;strong&gt;Data Ingestion&lt;/strong&gt;: Platform pulls data from multiple systems of record&lt;/li&gt;
&lt;li&gt;🗄️ &lt;strong&gt;Data Storage&lt;/strong&gt;: All data written to S3 data backbone&lt;/li&gt;
&lt;li&gt;🤖 &lt;strong&gt;Model Execution&lt;/strong&gt;: Invokes existing and new platform-specific models&lt;/li&gt;
&lt;li&gt;⚙️ &lt;strong&gt;Rule Application&lt;/strong&gt;: EMR applies thousands of YAML-defined business rules&lt;/li&gt;
&lt;li&gt;📤 &lt;strong&gt;Output Distribution&lt;/strong&gt;: Results routed to downstream systems via APIs and SNS&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Analytics Preparation&lt;/strong&gt;: Data prepared for regulatory and management tools&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Real-world engineering challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🏗️ Engineering Challenges at Scale
&lt;/h3&gt;

&lt;p&gt;Building this platform was &lt;strong&gt;not straightforward&lt;/strong&gt; - here's what the team faced:&lt;/p&gt;

&lt;h4&gt;
  
  
  Team &amp;amp; Process Challenges
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Challenge&lt;/th&gt;
&lt;th&gt;Scale&lt;/th&gt;
&lt;th&gt;Solution Approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Team coordination&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100+ engineers&lt;/td&gt;
&lt;td&gt;Standardized guardrails, coding standards, integration patterns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;System integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;76 upstream/downstream systems&lt;/td&gt;
&lt;td&gt;Careful API design, minimal disruption approach&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Program duration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multi-year timeline&lt;/td&gt;
&lt;td&gt;Consistent governance, regular architecture reviews&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Technical &amp;amp; Operational Challenges
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;💾 &lt;strong&gt;Data Volume&lt;/strong&gt;: Each scenario generates &lt;strong&gt;~500 TB&lt;/strong&gt; of data&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Required early archival strategy design&lt;/li&gt;
&lt;li&gt;Drove significant storage cost considerations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;⚡ &lt;strong&gt;Performance Optimization&lt;/strong&gt;: Multiple EMR clusters processing massive workloads&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimized cross-AZ traffic for latency reduction&lt;/li&gt;
&lt;li&gt;Controlled data transfer costs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;📈 &lt;strong&gt;Scaling Limits&lt;/strong&gt;: Constantly hitting AWS service quotas&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Continuous monitoring and quota increases&lt;/li&gt;
&lt;li&gt;Proactive capacity planning&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cost, performance, and reliability: applied Well-Architected
&lt;/h2&gt;

&lt;h3&gt;
  
  
  💰 Cost Optimization: Business Requirement, Not Nice-to-Have
&lt;/h3&gt;

&lt;p&gt;Cost optimization was treated as a &lt;strong&gt;business requirement&lt;/strong&gt;, with continuous architecture refinement using the Well-Architected Framework.&lt;/p&gt;

&lt;h4&gt;
  
  
  Optimization Strategies
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;S3 Partitioning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Smart data organization&lt;/td&gt;
&lt;td&gt;Reduced query costs, improved performance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Redshift Spectrum&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Analytics over S3 data&lt;/td&gt;
&lt;td&gt;Cost-efficient analytics without data movement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pre-partitioning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;S3 optimization&lt;/td&gt;
&lt;td&gt;Support for tens of millions TPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Real-time monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cost visibility framework&lt;/td&gt;
&lt;td&gt;Proactive cost management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pre-execution estimates&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;UI cost preview&lt;/td&gt;
&lt;td&gt;Business user cost awareness&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  EMR Fleet Strategy
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Mixed instance types and architectures&lt;/strong&gt; for optimal cost-performance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔧 &lt;strong&gt;Intel&lt;/strong&gt; processors for compatibility&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;AMD&lt;/strong&gt; processors for cost-performance balance
&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;AWS Graviton&lt;/strong&gt; for energy efficiency and cost savings&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Workload-based selection&lt;/strong&gt; for optimal resource utilization&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Measurable outcomes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📈 Measurable Outcomes: Transformational Results
&lt;/h3&gt;

&lt;p&gt;The transformation delivered &lt;strong&gt;significant&lt;/strong&gt; and &lt;strong&gt;measurable&lt;/strong&gt; improvements across all key metrics:&lt;/p&gt;

&lt;h4&gt;
  
  
  Performance &amp;amp; Cost Results
&lt;/h4&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;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infrastructure costs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;61% of baseline&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;39% reduction&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Execution time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;30% of baseline&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;70% reduction&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Manual processes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;40% of baseline&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;60% reduction&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;System execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~20 days&lt;/td&gt;
&lt;td&gt;~3 days&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;85% reduction&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Loan records/scenario&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~1.4M&lt;/td&gt;
&lt;td&gt;~36M&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;25x increase&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Operational Efficiency
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;📊 &lt;strong&gt;Scenario capacity&lt;/strong&gt;: &lt;strong&gt;20+&lt;/strong&gt; scenarios per month at massive scale&lt;/li&gt;
&lt;li&gt;👁️ &lt;strong&gt;Observability&lt;/strong&gt;: Dramatically improved monitoring and governance&lt;/li&gt;
&lt;li&gt;👥 &lt;strong&gt;Team efficiency&lt;/strong&gt;: From &lt;strong&gt;15 squads&lt;/strong&gt; (build) → &lt;strong&gt;2 squads&lt;/strong&gt; (support)&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Operational complexity&lt;/strong&gt;: Significant reduction in day-to-day management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These results represent a &lt;strong&gt;complete transformation&lt;/strong&gt; from a legacy, constraint-heavy system to a modern, scalable, cloud-native platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons you can apply
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🎓 Key Lessons for Your Organization
&lt;/h2&gt;

&lt;p&gt;The session concludes with actionable lessons that extend &lt;strong&gt;beyond this single use case&lt;/strong&gt;:&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Principle&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Marathon mindset&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Many sprints, not a big bang&lt;/td&gt;
&lt;td&gt;Sustainable progress, manageable risk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Celebrate incremental wins&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Acknowledge progress milestones&lt;/td&gt;
&lt;td&gt;Maintain team motivation, stakeholder support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;People over technology&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Focus on collaboration &amp;amp; governance&lt;/td&gt;
&lt;td&gt;Technology is an enabler, people determine success&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Business-first approach&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Start with problems, not solutions&lt;/td&gt;
&lt;td&gt;Ensures technology serves business objectives&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Non-Negotiable Foundations
&lt;/h3&gt;

&lt;h4&gt;
  
  
  🗄️ Data Quality &amp;amp; Governance
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Critical&lt;/strong&gt; for migration success&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Essential&lt;/strong&gt; for advanced analytics and AI enablement&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Must be established&lt;/strong&gt; from day one, not retrofitted&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  🤝 Agile Stakeholder Engagement
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Iterative collaboration&lt;/strong&gt; with business stakeholders&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous refinement&lt;/strong&gt; with cloud providers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture evolution&lt;/strong&gt; based on real-world feedback&lt;/li&gt;
&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Final Takeaway&lt;/strong&gt;: Successful large-scale migrations require a &lt;strong&gt;balanced approach&lt;/strong&gt; combining technical excellence, organizational change management, and continuous stakeholder engagement. Technology amplifies good processes and governance - it doesn't replace them.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>programming</category>
      <category>cloud</category>
      <category>architecture</category>
      <category>aws</category>
    </item>
    <item>
      <title>Linear and Canary releases in AWS ECS</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Sat, 08 Nov 2025 20:34:14 +0000</pubDate>
      <link>https://forem.com/ahmedadel/linear-and-canary-releases-in-aws-ecs-fhk</link>
      <guid>https://forem.com/ahmedadel/linear-and-canary-releases-in-aws-ecs-fhk</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/ahmedadel/next-level-deployments-in-aws-ecs-step-by-step-guide-to-linear-canary-releases-2025-edition-3bbb" class="crayons-story__hidden-navigation-link"&gt;💡 Next-Level Deployments in AWS ECS: Step-by-Step Guide to Linear &amp;amp; Canary Releases 🚀&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/ahmedadel" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F688023%2F6df3b916-a7ca-4b9d-a775-f3aa7c88c5d8.png" alt="ahmedadel profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/ahmedadel" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ahmed Adel
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ahmed Adel
                
              
              &lt;div id="story-author-preview-content-3001012" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/ahmedadel" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F688023%2F6df3b916-a7ca-4b9d-a775-f3aa7c88c5d8.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ahmed Adel&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/ahmedadel/next-level-deployments-in-aws-ecs-step-by-step-guide-to-linear-canary-releases-2025-edition-3bbb" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 7 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/ahmedadel/next-level-deployments-in-aws-ecs-step-by-step-guide-to-linear-canary-releases-2025-edition-3bbb" id="article-link-3001012"&gt;
          💡 Next-Level Deployments in AWS ECS: Step-by-Step Guide to Linear &amp;amp; Canary Releases 🚀
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/ahmedadel/next-level-deployments-in-aws-ecs-step-by-step-guide-to-linear-canary-releases-2025-edition-3bbb" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/ahmedadel/next-level-deployments-in-aws-ecs-step-by-step-guide-to-linear-canary-releases-2025-edition-3bbb#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>aws</category>
      <category>tutorial</category>
      <category>devops</category>
      <category>cicd</category>
    </item>
    <item>
      <title>💡 Next-Level Deployments in AWS ECS: Step-by-Step Guide to Linear &amp; Canary Releases 🚀</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Fri, 07 Nov 2025 12:43:32 +0000</pubDate>
      <link>https://forem.com/ahmedadel/next-level-deployments-in-aws-ecs-step-by-step-guide-to-linear-canary-releases-2025-edition-3bbb</link>
      <guid>https://forem.com/ahmedadel/next-level-deployments-in-aws-ecs-step-by-step-guide-to-linear-canary-releases-2025-edition-3bbb</guid>
      <description>&lt;p&gt;AWS ECS just dropped one of its most practical features for modern DevOps: &lt;strong&gt;built-in Linear and Canary deployments&lt;/strong&gt;! 😲 No more stitching together custom scripts or relying on external tools for smooth traffic-shifting and safer releases.&lt;/p&gt;

&lt;p&gt;Whether you’re all-in on microservices or just want to reduce the risk of production rollouts, this guide’s for you! Let’s get our hands dirty with a real ECS service so you can confidently say, “I did it!” ✌️&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Linear &amp;amp; Canary Deployments? 🧐
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Safer Updates:&lt;/strong&gt; Gradually test new versions with real traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instant Rollbacks:&lt;/strong&gt; Detect issues and revert 🚨 fast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation:&lt;/strong&gt; Support from AWS Console, CLI, CloudFormation, CDK, Terraform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works with ALB &amp;amp; Service Connect:&lt;/strong&gt; Play nice with modern networking.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Hands-on: Update Your ECS Service with a Canary or Linear Deployment
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;🎨 We'll use plenty of screenshots and CLI output. You can grab icons or illustrations from AWS Console or use royalty-free image sites for ECS diagrams.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🛠️ Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Existing ECS service using ALB or ECS Service Connect.&lt;/li&gt;
&lt;li&gt;New Docker image version ready in ECR.&lt;/li&gt;
&lt;li&gt;Permissions to update services.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  1. Open the ECS Console &amp;amp; Select Your Service
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go to your ECS Cluster&lt;/li&gt;
&lt;li&gt;Pick the Service to update&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%2Fbej20z0o5fxlswcw3lxv.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%2Fbej20z0o5fxlswcw3lxv.png" alt=" " width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&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%2Fr14dbgbld3nnluycw320.png" alt=" " width="800" height="225"&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2. Hit “Deploy new revision” and Configure Deployment Settings
&lt;/h3&gt;

&lt;p&gt;You’ll now see new options: &lt;strong&gt;Linear&lt;/strong&gt; and &lt;strong&gt;Canary&lt;/strong&gt; deployments! 🎉&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%2Frqkyrhhh6a6onugcowx8.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%2Frqkyrhhh6a6onugcowx8.png" alt=" " width="800" height="367"&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%2Fw69e3v6dww25v7pcy31y.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%2Fw69e3v6dww25v7pcy31y.png" alt=" " width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&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%2Fo572imt40zg738bkdm7u.png" alt=" " width="800" height="427"&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3. Configure Deployment Params
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linear:&lt;/strong&gt; Set the step percentage (e.g. 20%). ECS will shift 20% ➡️ 40% ➡️ 60%... of live traffic to the new revision in intervals you specify.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canary:&lt;/strong&gt; Route just a slice (e.g. 10%) of traffic to the new revision. Let it bake, then move all over if healthy.&lt;/li&gt;
&lt;li&gt;Add CloudWatch alarms to trigger auto-rollbacks if things go wrong.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CLI Example for Linear

aws ecs update-service
--cluster my-cluster
--service my-service
--deployment-controller type=ECS
--deployment-configuration
deploymentType=Linear,stepPercentage=20,stepBakeTimeInMinutes=10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. (Optional) Add Deployment Hooks 🪝
&lt;/h3&gt;

&lt;p&gt;Pause for tests/validation between steps! Use AWS CLI or SDK to configure.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Watch the Magic Happen 🧙‍♂️
&lt;/h3&gt;

&lt;p&gt;You’ll see tasks update, traffic shift, and alarms ready to catch issues. Instant rollback if trouble is detected.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Usage: When Should You Use What?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linear&lt;/td&gt;
&lt;td&gt;Gradual releases, user testing&lt;/td&gt;
&lt;td&gt;Move 20% of traffic each step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Canary&lt;/td&gt;
&lt;td&gt;Quick prod validation&lt;/td&gt;
&lt;td&gt;Test 10%, then release to 100%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🎯 Pro-tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use deployment hooks for integration/health checks.&lt;/li&gt;
&lt;li&gt;Monitor everything with CloudWatch.&lt;/li&gt;
&lt;li&gt;Works great with both HTTP and gRPC APIs.&lt;/li&gt;
&lt;li&gt;Combine with ECS Service Connect for simple, secure service-to-service comms.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌟 Wrap-up
&lt;/h2&gt;

&lt;p&gt;This feature is &lt;strong&gt;fresh&lt;/strong&gt;, highly practical, and ready for you! Demos or code in this post won't be found in most tutorials (yet). Give it a try and tell your infra team you’re on the cutting edge! 🤓&lt;/p&gt;




&lt;p&gt;📝 &lt;strong&gt;Try it, share your results, and let me know if you want an in-depth look at deployment hooks or ECS Service Connect next!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;(Images: AWS product pages &amp;amp; console screenshots. Get creative with icons and emoji for your audience!)&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A Brief Guide to AWS SageMaker Services</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Sat, 05 Apr 2025 07:54:58 +0000</pubDate>
      <link>https://forem.com/ahmedadel/a-brief-guide-to-aws-sagemaker-services-3lkm</link>
      <guid>https://forem.com/ahmedadel/a-brief-guide-to-aws-sagemaker-services-3lkm</guid>
      <description>&lt;h1&gt;
  
  
  A Practical Tour of Key Amazon SageMaker Services
&lt;/h1&gt;

&lt;p&gt;Amazon SageMaker is a managed platform that helps teams build, train, and run machine learning (ML) workloads without stitching together separate tools. Instead of maintaining custom infrastructure for every stage of the ML lifecycle, you can rely on SageMaker components for data prep, training, deployment, monitoring, and governance. This article walks through several important SageMaker capabilities and how they fit into a modern ML workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. SageMaker Automatic Model Tuning
&lt;/h2&gt;

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

&lt;p&gt;SageMaker Automatic Model Tuning runs many training jobs with different hyperparameter settings and searches for the configuration that yields the best objective metric. It uses Bayesian optimization under the hood to decide which combination of hyperparameters to try next, so you do not have to manually run dozens of experiments yourself.&lt;/p&gt;

&lt;p&gt;Key benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cuts down on manual hyperparameter search effort.&lt;/li&gt;
&lt;li&gt;Often improves model quality by efficiently exploring the search space.
&lt;/li&gt;
&lt;li&gt;Works with built‑in, marketplace, and custom algorithms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/automatic-model-tuning.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. SageMaker Deployment and Inference
&lt;/h2&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%2Fcnhj6n2zomtdijpio1k3.gif" 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%2Fcnhj6n2zomtdijpio1k3.gif" alt="Deployment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SageMaker provides managed infrastructure to host trained models and expose them as endpoints or batch jobs, so you can serve predictions at scale without managing servers directly. It supports real‑time, batch, asynchronous, and serverless inference options, along with traffic‑splitting for A/B testing and safe rollouts.&lt;br&gt;
Common deployment patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real‑time endpoints for low‑latency prediction APIs. &lt;/li&gt;
&lt;li&gt;Batch transform for large, offline scoring jobs.
&lt;/li&gt;
&lt;li&gt;Asynchronous inference for long‑running requests.&lt;/li&gt;
&lt;li&gt;Serverless inference for spiky or low‑throughput workloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/deploy-model.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  3. SageMaker Studio
&lt;/h2&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%2Fhcs3tebgbqk7ii9rrwvs.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhcs3tebgbqk7ii9rrwvs.jpg" alt="Studio"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SageMaker Studio is a web‑based integrated development environment that centralizes many ML activities in a single visual interface.&lt;br&gt;
Within Studio, you can launch notebooks, run experiments, debug models, and monitor performance without constantly switching tools.&lt;/p&gt;

&lt;p&gt;Main capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Managed notebooks for exploration and prototyping.&lt;/li&gt;
&lt;li&gt;Experiment tracking to organize and compare runs.&lt;/li&gt;
&lt;li&gt;Debugging tools to inspect training behavior.
&lt;/li&gt;
&lt;li&gt;Built‑in monitoring views for deployed models.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/studio.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  4. SageMaker Data Wrangler
&lt;/h2&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%2Fdzubouesh3ijf535b84n.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%2Fdzubouesh3ijf535b84n.png" alt="DataWrangler"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Data Wrangler is designed to shorten the “data cleaning and feature engineering” phase by providing a visual workspace for data preparation. You can connect to data sources, explore data distributions, apply transformations, and then export the prepared dataset into downstream SageMaker workflows.&lt;/p&gt;

&lt;p&gt;What you can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apply hundreds of built‑in data transformations and feature ops.
&lt;/li&gt;
&lt;li&gt;Visualize data quality and distributions as you iterate.
&lt;/li&gt;
&lt;li&gt;Engineer features and send them into SageMaker Pipelines.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/data-wrangler.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  5. SageMaker Clarify
&lt;/h2&gt;

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

&lt;p&gt;SageMaker Clarify provides bias and explainability tooling for your ML models, helping you understand both how they behave and how they might impact different user groups. It analyzes training data and predictions to surface fairness metrics and generate feature‑importance explanations.&lt;/p&gt;

&lt;p&gt;Key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bias detection metrics on datasets and model outputs.
&lt;/li&gt;
&lt;li&gt;Model explainability reports for stakeholders.
&lt;/li&gt;
&lt;li&gt;Feature importance for both global and local explanations.
&lt;/li&gt;
&lt;li&gt;Support for compliance and responsible‑AI requirements.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/clarify.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  6. SageMaker Ground Truth
&lt;/h2&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%2Frmcjtog3odzxv75r22si.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%2Frmcjtog3odzxv75r22si.png" alt="Ground Truth"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ground Truth helps you build labeled datasets by managing annotation workflows and integrating with human labelers. You can use Amazon’s own workforce, third‑party vendors, or your internal team, depending on the data sensitivity and scale requirements.&lt;/p&gt;

&lt;p&gt;Labeling options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public workforce through Amazon Mechanical Turk.
&lt;/li&gt;
&lt;li&gt;Vendor workforces managed by AWS partners.
&lt;/li&gt;
&lt;li&gt;Private labeling teams within your organization.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/sms.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  7. SageMaker Model Cards
&lt;/h2&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%2Ffmw9hhaavw0hl107gbje.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%2Ffmw9hhaavw0hl107gbje.png" alt="Model Cards"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Model Cards in SageMaker provide a structured template for documenting important details about each model, which is critical for governance and audits. They centralize context like intended use, training data characteristics, and evaluation metrics in a standardized format.&lt;/p&gt;

&lt;p&gt;Typical sections include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High‑level model description and owners.
&lt;/li&gt;
&lt;li&gt;Expected use cases and known limitations.
&lt;/li&gt;
&lt;li&gt;Training data sources and configuration.
&lt;/li&gt;
&lt;li&gt;Evaluation methodology and performance results.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/model-cards.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  8. SageMaker Model Dashboard
&lt;/h2&gt;

&lt;p&gt;SageMaker Model Dashboard offers a unified view across models that are running in production so teams can track health and risk in one place. It aggregates information from monitoring tools to help you see which models might require retraining or investigation.&lt;/p&gt;

&lt;p&gt;Core capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tracking model performance indicators over time.
&lt;/li&gt;
&lt;li&gt;Detecting data and prediction drift patterns.
&lt;/li&gt;
&lt;li&gt;Configuring alerts and notifications for issues.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/model-dashboard.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  9. SageMaker Model Monitor
&lt;/h2&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%2Fz52k75g4c77r7eupxbc1.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz52k75g4c77r7eupxbc1.JPG" alt="Model Monitor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Model Monitor continuously evaluates the quality of models deployed in SageMaker by comparing live traffic to a defined baseline. When it detects drift or quality issues, it can surface alerts so you can decide whether to retrain, roll back, or adjust the model.&lt;/p&gt;

&lt;p&gt;Things it can monitor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input data quality and schema consistency.
&lt;/li&gt;
&lt;li&gt;Prediction quality and performance metrics.
&lt;/li&gt;
&lt;li&gt;Bias drift over time on key attributes.
&lt;/li&gt;
&lt;li&gt;Changes in feature attribution patterns.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/model-monitor.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  10. SageMaker Model Registry
&lt;/h2&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%2Fx7tjfopfya1vl8go8bfd.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%2Fx7tjfopfya1vl8go8bfd.png" alt="Registry"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Model Registry is a catalog for your trained models, enabling controlled promotion from experimentation to production. It tracks versions, metadata, and approval states so that ML and MLOps teams can coordinate deployments more safely.&lt;/p&gt;

&lt;p&gt;Key capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Versioning of model artifacts and metadata.
&lt;/li&gt;
&lt;li&gt;Approval workflows for moving models between stages.
&lt;/li&gt;
&lt;li&gt;Lineage tracking across training, evaluation, and deployment.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/model-registry.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  11. SageMaker Pipelines
&lt;/h2&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%2Fh8y4s5qcye285hie0dne.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%2Fh8y4s5qcye285hie0dne.png" alt="Pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SageMaker Pipelines is a purpose‑built workflow engine for ML that lets you define and automate multi‑step pipelines, from preprocessing to training to deployment. Pipelines make ML workflows reproducible, repeatable, and easier to integrate with CI/CD systems.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensures reproducible runs with versioned definitions.
&lt;/li&gt;
&lt;li&gt;Encourages reusability of standardized pipeline steps.
&lt;/li&gt;
&lt;li&gt;Integrates with DevOps tooling for automated releases.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/pipelines.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  12. SageMaker Role Manager
&lt;/h2&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%2Fkynmpikqmidziy7uk4du.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%2Fkynmpikqmidziy7uk4du.png" alt="Role Manager"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Role Manager simplifies the process of configuring permissions for SageMaker resources by offering templates and guided workflows. Instead of manually writing complex IAM policies, you can start from predefined roles and then adjust them as needed.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Curated roles for common SageMaker usage patterns.
&lt;/li&gt;
&lt;li&gt;Fine‑grained permission controls for security teams.
&lt;/li&gt;
&lt;li&gt;Tight integration with AWS Identity and Access Management (IAM).
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-roles.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  13. SageMaker JumpStart
&lt;/h2&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%2F0x0g7fddpj0153g6pp1z.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%2F0x0g7fddpj0153g6pp1z.png" alt="JumpStart"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JumpStart provides a gallery of pre‑built solutions, pre‑trained models, and example notebooks that you can deploy or customize with just a few steps. It is particularly useful when you want to quickly prototype a use case like classification, forecasting, or computer vision without building everything from scratch.&lt;/p&gt;

&lt;p&gt;What JumpStart offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ready‑to‑use pre‑trained models for common tasks.
&lt;/li&gt;
&lt;li&gt;End‑to‑end solution templates with infrastructure code.
&lt;/li&gt;
&lt;li&gt;Example notebooks you can open directly in Studio.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/studio-jumpstart.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  14. SageMaker Canvas
&lt;/h2&gt;

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

&lt;p&gt;SageMaker Canvas targets business users who want to generate predictions without writing code or managing infrastructure. It provides a visual interface where users can connect data, build ML models with AutoML, and explore predictions interactively.&lt;/p&gt;

&lt;p&gt;Key traits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drag‑and‑drop interface for non‑technical users.
&lt;/li&gt;
&lt;li&gt;Automatic model building and selection behind the scenes.
&lt;/li&gt;
&lt;li&gt;Focus on business‑friendly workflows and collaboration.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/canvas.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  15. SageMaker MLflow Integration
&lt;/h2&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%2Fboeuss2yv66r2msdvmvp.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%2Fboeuss2yv66r2msdvmvp.png" alt="MLFlow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SageMaker integrates with the open‑source MLflow ecosystem so that teams already using MLflow for experiment tracking and model management can tie those workflows into SageMaker services. This integration lets you log runs, track artifacts, and manage model versions while still deploying on SageMaker.&lt;/p&gt;

&lt;p&gt;You can use it to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Track experiments and metrics in MLflow while training on SageMaker.
&lt;/li&gt;
&lt;li&gt;Register models in an MLflow registry and connect them to SageMaker deployments.
&lt;/li&gt;
&lt;li&gt;Store training artifacts in a centralized and queryable location.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/mlflow.html" rel="noopener noreferrer"&gt;Read more&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;AWS SageMaker brings together many specialized services that collectively cover data preparation, experimentation, deployment, monitoring, and governance for ML workloads. By adopting the right mix of these tools, teams can shorten development cycles and operate ML systems more reliably at scale.&lt;/p&gt;

&lt;p&gt;For deeper dives into specific features, see the &lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/whatis.html" rel="noopener noreferrer"&gt;official SageMaker documentation&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AWS SageMaker Documentation.&lt;/li&gt;
&lt;li&gt;AWS Machine Learning Blog.
&lt;/li&gt;
&lt;li&gt;AWS re:Invent sessions and technical talks.
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>🚀 EBS Volumes for EC2: Should You Use Multiple Small Volumes or One Large Volume? 💡</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Tue, 07 Jan 2025 13:30:44 +0000</pubDate>
      <link>https://forem.com/aws-builders/ebs-volumes-for-ec2-should-you-use-multiple-small-volumes-or-one-large-volume-1ei0</link>
      <guid>https://forem.com/aws-builders/ebs-volumes-for-ec2-should-you-use-multiple-small-volumes-or-one-large-volume-1ei0</guid>
      <description>&lt;h1&gt;
  
  
  🚀 Attaching Persistent EBS Volumes to EC2: Multiple Small Volumes vs. One Large Volume 🚀
&lt;/h1&gt;

&lt;p&gt;When working with &lt;strong&gt;Containers in Amazon EC2&lt;/strong&gt;, you might need to attach &lt;strong&gt;persistent EBS (Elastic Block Store) volumes&lt;/strong&gt; to your containers. But what if you have &lt;strong&gt;multiple containers&lt;/strong&gt;, and each one needs its own storage? Should you create &lt;strong&gt;multiple smaller EBS volumes&lt;/strong&gt; or &lt;strong&gt;one large volume&lt;/strong&gt;? Let’s break it down! 💡&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 The Dilemma: Multiple Small Volumes vs. One Large Volume
&lt;/h2&gt;

&lt;p&gt;Imagine you have &lt;strong&gt;5 containers&lt;/strong&gt;, and each needs &lt;strong&gt;20 GB of persistent storage&lt;/strong&gt;. You have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create 5 separate EBS volumes&lt;/strong&gt; (20 GB each).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create 1 large EBS volume&lt;/strong&gt; (100 GB) and share it among the containers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Which one should you choose? Let’s explore the &lt;strong&gt;cost&lt;/strong&gt;, &lt;strong&gt;performance&lt;/strong&gt;, and &lt;strong&gt;management&lt;/strong&gt; implications of each approach. 🧐&lt;/p&gt;




&lt;h2&gt;
  
  
  💰 Cost: Is There a Difference?
&lt;/h2&gt;

&lt;p&gt;The cost of EBS volumes depends on the &lt;strong&gt;size&lt;/strong&gt;, &lt;strong&gt;type&lt;/strong&gt;, and &lt;strong&gt;usage duration&lt;/strong&gt;. Here’s the breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EBS Pricing Model&lt;/strong&gt;: You pay for the &lt;strong&gt;provisioned storage size&lt;/strong&gt; (per GB per month), regardless of how much data you actually store.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost Comparison&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;5 x 20 GB Volumes&lt;/strong&gt;: If each 20 GB volume costs $X per month, then 5 volumes would cost &lt;strong&gt;5 × $X&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1 x 100 GB Volume&lt;/strong&gt;: A single 100 GB volume would cost &lt;strong&gt;1 × $X&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In most cases, the &lt;strong&gt;total cost for 5 x 20 GB volumes is the same as 1 x 100 GB volume&lt;/strong&gt;. However, if you use advanced features like &lt;strong&gt;provisioned IOPS&lt;/strong&gt;, the cost may vary slightly.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Performance: Isolation vs. Shared Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Multiple Smaller Volumes&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Each EBS volume has its own &lt;strong&gt;IOPS (Input/Output Operations Per Second)&lt;/strong&gt; and &lt;strong&gt;throughput limits&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If your containers have &lt;strong&gt;independent I/O workloads&lt;/strong&gt;, multiple smaller volumes provide &lt;strong&gt;better performance isolation&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;One container’s I/O won’t affect another.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Single Larger Volume&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A single 100 GB volume has &lt;strong&gt;higher aggregate IOPS and throughput&lt;/strong&gt; compared to a 20 GB volume.&lt;/li&gt;
&lt;li&gt;However, if multiple containers share the same volume, their I/O workloads may &lt;strong&gt;compete for resources&lt;/strong&gt;, leading to potential bottlenecks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Management: Complexity vs. Simplicity
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Multiple Smaller Volumes&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You’ll need to &lt;strong&gt;attach and manage each volume separately&lt;/strong&gt; to the EC2 instance.&lt;/li&gt;
&lt;li&gt;Each container will need its own &lt;strong&gt;mount point&lt;/strong&gt; on the EC2 instance.&lt;/li&gt;
&lt;li&gt;This approach is more complex but provides &lt;strong&gt;better isolation&lt;/strong&gt; for each container.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Single Larger Volume&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easier to manage since you only need to &lt;strong&gt;attach and mount one volume&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You can create &lt;strong&gt;subdirectories&lt;/strong&gt; on the volume for each container and mount them separately in the ECS task definition.&lt;/li&gt;
&lt;li&gt;However, this approach requires careful planning to avoid &lt;strong&gt;I/O contention&lt;/strong&gt; between containers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏆 Recommendations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use Multiple Smaller Volumes (5 x 20 GB)&lt;/strong&gt; if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Each container has &lt;strong&gt;independent I/O workloads&lt;/strong&gt; and requires &lt;strong&gt;performance isolation&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You want to avoid &lt;strong&gt;I/O contention&lt;/strong&gt; between containers.&lt;/li&gt;
&lt;li&gt;You are okay with the additional &lt;strong&gt;management overhead&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use a Single Larger Volume (1 x 100 GB)&lt;/strong&gt; if:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The containers have &lt;strong&gt;low I/O workloads&lt;/strong&gt; and can share the same volume without contention.&lt;/li&gt;
&lt;li&gt;You want to &lt;strong&gt;simplify management&lt;/strong&gt; and reduce the number of volumes to monitor.&lt;/li&gt;
&lt;li&gt;You can use &lt;strong&gt;subdirectories&lt;/strong&gt; to logically separate data for each container.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Example Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Option 1: Multiple Smaller Volumes&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create 5 EBS volumes (20 GB each).&lt;/li&gt;
&lt;li&gt;Attach all 5 volumes to the EC2 instance.&lt;/li&gt;
&lt;li&gt;Mount each volume to a separate directory (e.g., &lt;code&gt;/mnt/volume1&lt;/code&gt;, &lt;code&gt;/mnt/volume2&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;In the ECS task definition, map each container to its respective volume mount point.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Option 2: Single Larger Volume&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create 1 EBS volume (100 GB).&lt;/li&gt;
&lt;li&gt;Attach the volume to the EC2 instance.&lt;/li&gt;
&lt;li&gt;Mount the volume to a directory (e.g., &lt;code&gt;/mnt/shared-volume&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Create subdirectories for each container (e.g., &lt;code&gt;/mnt/shared-volume/container1&lt;/code&gt;, &lt;code&gt;/mnt/shared-volume/container2&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;In the ECS task definition, map each container to its respective subdirectory.&lt;/li&gt;
&lt;/ol&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt;: The total cost for 5 x 20 GB volumes is likely the same as 1 x 100 GB volume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Multiple smaller volumes provide better performance isolation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Management&lt;/strong&gt;: A single larger volume is easier to manage but may lead to I/O contention.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choose the approach that best fits your &lt;strong&gt;performance requirements&lt;/strong&gt; and &lt;strong&gt;management preferences&lt;/strong&gt;. If you need &lt;strong&gt;isolation and independent performance&lt;/strong&gt;, go with multiple smaller volumes. If you prefer &lt;strong&gt;simplicity and shared storage&lt;/strong&gt;, use a single larger volume.&lt;/p&gt;

&lt;p&gt;Happy deploying! 🚀&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What’s your take?&lt;/strong&gt; Do you prefer multiple smaller volumes or one large volume? Let’s discuss in the comments! 👇&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>ec2</category>
      <category>aws</category>
    </item>
    <item>
      <title>AWS re:Invent 2024 - Zero to production serverless in 8 weeks</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Sun, 22 Dec 2024 17:33:54 +0000</pubDate>
      <link>https://forem.com/aws-builders/aws-reinvent-2024-zero-to-production-serverless-in-8-weeks-3708</link>
      <guid>https://forem.com/aws-builders/aws-reinvent-2024-zero-to-production-serverless-in-8-weeks-3708</guid>
      <description>&lt;h1&gt;
  
  
  🚀 Building an ADHD Prescription Integration Under Tight Deadlines Using Serverless Architecture 🌐💊
&lt;/h1&gt;

&lt;p&gt;In early 2024, we embarked on an exciting but challenging project at &lt;strong&gt;Chemist4U&lt;/strong&gt;, the UK's third-largest online pharmacy dispensing an impressive &lt;strong&gt;175,000–200,000 items monthly&lt;/strong&gt;. Our mission? To build a secure, scalable integration for a &lt;strong&gt;clinic specializing in ADHD diagnostics and treatment&lt;/strong&gt;. This new system would replace the clinic’s existing pharmacy partner, which struggled to scale alongside their growing demand.&lt;/p&gt;

&lt;p&gt;With tight deadlines and high stakes, this project was a race against time to ensure patients could continue receiving critical medications without any interruption. Here's how we made it happen! 💪&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 The Challenge: What Did We Need to Solve?
&lt;/h2&gt;

&lt;p&gt;We were tasked with building a comprehensive solution that tackled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Secure Data Integration:&lt;/strong&gt; A safe, reliable way to transfer sensitive patient and prescription data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regulatory Compliance:&lt;/strong&gt; ADHD medications are &lt;strong&gt;highly controlled&lt;/strong&gt;, requiring checks on patient history and strict adherence to UK regulations.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seamless Payment Handling:&lt;/strong&gt; Private prescriptions needed secure payment processing, while NHS prescriptions required accurate invoicing for reimbursements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer Service Enablement:&lt;/strong&gt; Equipping the support team with tools to answer patient inquiries effectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warehouse Integration:&lt;/strong&gt; Ensuring prescriptions were processed smoothly by our ERP and warehouse systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deadline:&lt;/strong&gt; Eight weeks ⏳&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Why Serverless?
&lt;/h2&gt;

&lt;p&gt;Given the complexity and urgency, &lt;strong&gt;serverless architecture&lt;/strong&gt; was the perfect choice. Here's why:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;⚙️ Built-in High Availability:&lt;/strong&gt; No need to manage uptime—it’s baked in.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📉 Low Administration Overhead:&lt;/strong&gt; Skip the headache of managing EC2 instances or Kubernetes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🚀 Rapid Development:&lt;/strong&gt; Tools like AWS CDK allowed us to prototype and deploy features faster.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📈 Auto Scaling:&lt;/strong&gt; Effortlessly handle peaks and troughs in prescription volume.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Curious about serverless?&lt;/strong&gt; Check out &lt;a href="https://aws.amazon.com/serverless/" rel="noopener noreferrer"&gt;AWS’s guide to serverless architecture&lt;/a&gt;. 🌟&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  💡 The Approach: Prototyping First
&lt;/h2&gt;

&lt;p&gt;We skipped the &lt;strong&gt;proof of concept&lt;/strong&gt; stage and dove straight into building a &lt;strong&gt;working prototype&lt;/strong&gt;. Prototyping allowed us to test our ideas in real-world conditions while leaving room for rapid iterations.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠 Tools and Technologies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://aws.amazon.com/cdk/" rel="noopener noreferrer"&gt;AWS CDK&lt;/a&gt;:&lt;/strong&gt; For Infrastructure as Code (IaC).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;Vitest&lt;/a&gt;:&lt;/strong&gt; Unit testing from Day 1 ensured reliability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://biomejs.dev/" rel="noopener noreferrer"&gt;Biome&lt;/a&gt;:&lt;/strong&gt; Automated linting and formatting saved valuable time.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hexagonal Architecture:&lt;/strong&gt; Enabled modular development—essential for teamwork!
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.serverless.com/" rel="noopener noreferrer"&gt;Serverless Framework&lt;/a&gt;:&lt;/strong&gt; Combined with &lt;strong&gt;AWS Lambda&lt;/strong&gt;, &lt;strong&gt;API Gateway&lt;/strong&gt;, and &lt;strong&gt;DynamoDB&lt;/strong&gt; for backend functionality.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;React with Vite&lt;/a&gt;:&lt;/strong&gt; For the front-end interface.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🎉 Day 1 Wins!
&lt;/h3&gt;

&lt;p&gt;By leveraging pre-built boilerplate code and automation tools, we launched:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A basic &lt;strong&gt;authenticated website&lt;/strong&gt; using &lt;strong&gt;AWS Cognito&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;A stubbed API with validation powered by &lt;strong&gt;API Gateway&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;CI/CD pipelines for automated deployments.
&lt;/li&gt;
&lt;li&gt;Fully isolated developer environments for efficient parallel work.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏗️ Building the Core Integration
&lt;/h2&gt;

&lt;p&gt;The centerpiece of the system was the integration with the clinic’s existing platform. Here's how we approached it:&lt;/p&gt;

&lt;h3&gt;
  
  
  1️⃣ Defining Interfaces Early
&lt;/h3&gt;

&lt;p&gt;To avoid delays, we deployed a &lt;strong&gt;stubbed API&lt;/strong&gt; with validation using Swagger. This allowed the clinic’s team to proceed with development in parallel.&lt;/p&gt;

&lt;h3&gt;
  
  
  2️⃣ Validation Handling
&lt;/h3&gt;

&lt;p&gt;Initially, we used API Gateway’s built-in validation. However, the &lt;strong&gt;generic error messages&lt;/strong&gt; were a bottleneck during testing. Switching to &lt;strong&gt;Zod&lt;/strong&gt; gave us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customizable validation messages.
&lt;/li&gt;
&lt;li&gt;Consistent logic reuse in &lt;strong&gt;TypeScript&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Cleaner, more actionable error handling.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ⚡ Infrastructure Setup with AWS CDK
&lt;/h3&gt;

&lt;p&gt;Our serverless architecture consisted of:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Gateway&lt;/strong&gt;: Managed RESTful API endpoints.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lambda Functions&lt;/strong&gt;: Executed core business logic.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DynamoDB&lt;/strong&gt;: Stored prescription and patient data securely.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3 Buckets&lt;/strong&gt;: Hosted the React front end and stored documents.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Want to learn CDK?&lt;/strong&gt; Check out this &lt;a href="https://docs.aws.amazon.com/cdk/latest/guide/home.html" rel="noopener noreferrer"&gt;CDK documentation&lt;/a&gt;. 📚  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🌈 Rapid Iterations with Serverless
&lt;/h3&gt;

&lt;p&gt;Serverless enabled us to:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quickly deploy isolated development environments.
&lt;/li&gt;
&lt;li&gt;Make reproducible changes using &lt;strong&gt;IaC&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Maintain stability with &lt;strong&gt;automated tests&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;💡 &lt;strong&gt;Prototyping is Key:&lt;/strong&gt; Starting with a working prototype minimized rework.&lt;br&gt;&lt;br&gt;
💡 &lt;strong&gt;Better Error Handling Matters:&lt;/strong&gt; Switching to Zod drastically improved testing efficiency.&lt;br&gt;&lt;br&gt;
💡 &lt;strong&gt;Serverless Speeds Things Up:&lt;/strong&gt; By offloading infrastructure management, we could focus on delivering business value.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 The Result
&lt;/h2&gt;

&lt;p&gt;In just &lt;strong&gt;8 weeks&lt;/strong&gt;, we delivered a fully functional system that:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secured sensitive patient data 🔒.
&lt;/li&gt;
&lt;li&gt;Automated workflows adhering to strict regulations ✅.
&lt;/li&gt;
&lt;li&gt;Integrated seamlessly with the clinic and warehouse systems ⚡.
&lt;/li&gt;
&lt;li&gt;Scaled to meet the growing demand for ADHD prescriptions 📈.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📺 Original Video
&lt;/h2&gt;

&lt;p&gt;Want to dive deeper into our process? Watch the original video on YouTube:  &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;iframe width="710" height="399" src="https://www.youtube.com/embed/_ylQ6qVBq9E"&gt;
&lt;/iframe&gt;

&lt;/h2&gt;

&lt;p&gt;What do you think of our approach? Have you worked on similar tight-deadline projects? Let us know in the comments! 👇&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>serverless</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Hands-On: Deploy a Web App on an Nginx Server Using AWS App Runner</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Tue, 17 Dec 2024 19:02:25 +0000</pubDate>
      <link>https://forem.com/aws-builders/hands-on-deploy-a-web-app-on-an-nginx-server-using-aws-app-runner-3mac</link>
      <guid>https://forem.com/aws-builders/hands-on-deploy-a-web-app-on-an-nginx-server-using-aws-app-runner-3mac</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;In this tutorial, you will learn how to deploy a containerized application on an Nginx server using &lt;strong&gt;AWS App Runner&lt;/strong&gt;. This hands-on guide is perfect for beginners and covers everything from building a container image to deploying it via App Runner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS App Runner&lt;/strong&gt; is a fully managed service that enables you to deploy containerized web applications and APIs at scale, with minimal effort. Whether you're starting with source code or a container image, App Runner takes care of the heavy lifting: automatic builds, deployments, load balancing, and traffic scaling.&lt;/p&gt;

&lt;h3&gt;
  
  
  What You Will Accomplish
&lt;/h3&gt;

&lt;p&gt;By the end of this tutorial, you will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a container image for your web app.&lt;/li&gt;
&lt;li&gt;Push the image to &lt;strong&gt;Amazon Elastic Container Registry (ECR)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Deploy the image using &lt;strong&gt;AWS App Runner&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Clean up resources to avoid additional charges.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before diving into the steps, ensure you have:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;An &lt;a href="https://aws.amazon.com/getting-started/guides/setup-environment/" rel="noopener noreferrer"&gt;AWS Account&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the account has administrator-level access. Accounts created within the past 24 hours may not have access to required services.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AWS Command Line Interface (CLI)&lt;/strong&gt; installed and configured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/cli/" rel="noopener noreferrer"&gt;Get started with AWS CLI&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Docker Engine&lt;/strong&gt; installed and running:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow the &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker installation guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Visual Studio Code&lt;/strong&gt; (or your preferred code editor):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Download Visual Studio Code&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Time and Cost
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time:&lt;/strong&gt; ~20 minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; Less than $0.16 (if completed within two hours and resources are deleted at the end).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Create a Container Image
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1 Set Up Your Project
&lt;/h3&gt;

&lt;p&gt;Open a terminal and run the following commands to create a new directory for your project:&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;mkdir &lt;/span&gt;nginx-web-app
&lt;span class="nb"&gt;cd &lt;/span&gt;nginx-web-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.2 Create the Web Page
&lt;/h3&gt;

&lt;p&gt;Open the &lt;code&gt;nginx-web-app&lt;/code&gt; folder in Visual Studio Code (or your code editor). Inside this folder:&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%2Fdf1i2e1lzrdu3g9ns29s.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%2Fdf1i2e1lzrdu3g9ns29s.png" alt=" " width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new file named &lt;code&gt;index.html&lt;/code&gt; and paste the following code:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pe73ja314x52sekfopl.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%2F5pe73ja314x52sekfopl.png" alt=" " width="526" height="426"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Sample Web App&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;light&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;35em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Amazon&lt;/span&gt; &lt;span class="n"&gt;Ember&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Verdana&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to AWS App Runner!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;If you see this page, the Nginx web server is successfully installed and working.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;&lt;/span&gt;Thank you for using AWS App Runner!&lt;span class="nt"&gt;&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


![ ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpb5yllbmewq0etrlp3m.png)


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

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.3 Create a Dockerfile
&lt;/h3&gt;

&lt;p&gt;Create another file named &lt;code&gt;Dockerfile&lt;/code&gt; in the same folder and add the following content:&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; --platform=linux/amd64 nginx:latest&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/share/nginx/html&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; index.html index.html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2mkm200k5qbkzr4u14jx.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%2F2mkm200k5qbkzr4u14jx.png" alt=" " width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1.4 Build the Container Image
&lt;/h3&gt;

&lt;p&gt;Run the following command in the terminal to build the Docker image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; nginx-web-app &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7q7k5p5cp51pi99vb0z.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%2Fx7q7k5p5cp51pi99vb0z.png" alt=" " width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Push Container Image to Amazon ECR
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 Create a Repository
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Sign in to the &lt;a href="https://console.aws.amazon.com/ecr/home" rel="noopener noreferrer"&gt;Amazon ECR Console&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvj738e5ea88qs8w552t.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%2Fgvj738e5ea88qs8w552t.png" alt=" " width="800" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Create Repository&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftq5n3q1s4fqyh5vyvepq.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%2Ftq5n3q1s4fqyh5vyvepq.png" alt=" " width="800" height="820"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enter &lt;code&gt;nginx-web-app&lt;/code&gt; as the repository name and leave the defaults. Click &lt;strong&gt;Create Repository&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1i58nol0f9ldajyeih5y.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%2F1i58nol0f9ldajyeih5y.png" alt=" " width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Push the Image to ECR
&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%2Fwrk8ysdw9eyx8wfmkwzm.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%2Fwrk8ysdw9eyx8wfmkwzm.png" alt=" " width="796" height="706"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the newly created repository and click &lt;strong&gt;View push commands&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Follow the push commands provided, which typically include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authenticating Docker with ECR:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; &amp;lt;region&amp;gt; | docker login &lt;span class="nt"&gt;--username&lt;/span&gt; AWS &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; &amp;lt;account_id&amp;gt;.dkr.ecr.&amp;lt;region&amp;gt;.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Tagging the image:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag nginx-web-app:latest &amp;lt;account_id&amp;gt;.dkr.ecr.&amp;lt;region&amp;gt;.amazonaws.com/nginx-web-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pushing the image:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker push &amp;lt;account_id&amp;gt;.dkr.ecr.&amp;lt;region&amp;gt;.amazonaws.com/nginx-web-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 3: Create an AWS App Runner Service
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://console.aws.amazon.com/apprunner/home" rel="noopener noreferrer"&gt;AWS App Runner Console&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyumddzc06k8dftbd2021.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%2Fyumddzc06k8dftbd2021.png" alt=" " width="800" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Create an App Runner service&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqb05i9bw5cr7byr1k9dh.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%2Fqb05i9bw5cr7byr1k9dh.png" alt=" " width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;strong&gt;Source and Deployment&lt;/strong&gt; section:

&lt;ul&gt;
&lt;li&gt;Select &lt;strong&gt;Amazon ECR&lt;/strong&gt; as the source.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Browse&lt;/strong&gt; and select the &lt;code&gt;nginx-web-app&lt;/code&gt; repository.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcq4y0aqlzdixpqmvbur1.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%2Fcq4y0aqlzdixpqmvbur1.png" alt=" " width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In &lt;strong&gt;Deployment Settings&lt;/strong&gt;, select &lt;strong&gt;Create new service role&lt;/strong&gt; and click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjh1k36d1ovkld9993jsd.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%2Fjh1k36d1ovkld9993jsd.png" alt=" " width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On the &lt;strong&gt;Configure Service&lt;/strong&gt; page:

&lt;ul&gt;
&lt;li&gt;Enter &lt;code&gt;nginx-web-app-service&lt;/code&gt; as the Service Name.&lt;/li&gt;
&lt;li&gt;Set the Port to &lt;code&gt;80&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fem0phtb7r6f6b0btzpud.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%2Fem0phtb7r6f6b0btzpud.png" alt=" " width="800" height="1266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Review the configuration on the next page and click &lt;strong&gt;Create &amp;amp; Deploy&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpy7n2k0tx93qe5q7o4wc.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%2Fpy7n2k0tx93qe5q7o4wc.png" alt=" " width="800" height="1076"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Wait for the service to deploy. Once the status changes to &lt;strong&gt;Running&lt;/strong&gt;, click the default domain name to view your web app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdqgyax4qfox72ntjp0gu.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%2Fdqgyax4qfox72ntjp0gu.png" alt=" " width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Once the status updates to Running, choose the default domain name URL to view the web app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jfgz5ch8n651u4fqcs6.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%2F9jfgz5ch8n651u4fqcs6.png" alt=" " width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Welcome page and confirmation message should look like the image on the right.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxlkz67vkqnnsykwx3s6.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%2Fvxlkz67vkqnnsykwx3s6.png" alt=" " width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Clean Up Resources
&lt;/h2&gt;

&lt;p&gt;To avoid additional charges, delete the resources you created:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;strong&gt;AWS App Runner Console&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Navigate to your service.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Actions&lt;/strong&gt; &amp;gt; &lt;strong&gt;Delete&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9ntfu2fhb24m650zcpz.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%2Fy9ntfu2fhb24m650zcpz.png" alt=" " width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://d1.awsstatic.com/Getting%20Started/tutorials/deploy-web-app-ngnix-app-runner/web-app-nginx-apprunner-4.2.d748703fb97dd7dace326ca9dfc144d89bcfcd86.png" rel="noopener noreferrer"&gt;https://d1.awsstatic.com/Getting%20Started/tutorials/deploy-web-app-ngnix-app-runner/web-app-nginx-apprunner-4.2.d748703fb97dd7dace326ca9dfc144d89bcfcd86.png&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;strong&gt;Amazon ECR Console&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Select the &lt;code&gt;nginx-web-app&lt;/code&gt; repository.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Delete&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8967z59lobfgkgo79eyp.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%2F8967z59lobfgkgo79eyp.png" alt=" " width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Congratulations! You have successfully deployed a containerized Nginx web application using AWS App Runner. This guide introduced you to building container images, using Amazon ECR, and the power of AWS App Runner for seamless deployment.&lt;/p&gt;

&lt;p&gt;Feel free to experiment further and explore advanced features like custom domains or continuous deployment pipelines. For more resources, check out the &lt;a href="https://aws.amazon.com/apprunner/" rel="noopener noreferrer"&gt;AWS App Runner documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding! 🎉&lt;/p&gt;

</description>
      <category>aws</category>
      <category>nginx</category>
      <category>web</category>
      <category>cloud</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Wed, 04 Dec 2024 03:33:57 +0000</pubDate>
      <link>https://forem.com/ahmedadel/-2l8n</link>
      <guid>https://forem.com/ahmedadel/-2l8n</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/aws-builders" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&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%2Forganization%2Fprofile_image%2F2794%2F88da75b6-aadd-4ea1-8083-ae2dfca8be94.png" alt="AWS Community Builders " width="350" height="350"&gt;
      &lt;div class="ltag__link__user__pic"&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%2Fuser%2Fprofile_image%2F688023%2F6df3b916-a7ca-4b9d-a775-f3aa7c88c5d8.png" alt="" width="800" height="800"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/aws-builders/discover-amazon-s3-metadata-a-new-way-to-explore-your-storage-at-aws-reinvent-2024-4ijn" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Discover Amazon S3 Metadata: A New Way to Explore Your Storage at AWS re:Invent 2024&lt;/h2&gt;
      &lt;h3&gt;Ahmed Adel for AWS Community Builders  ・ Dec 4 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#aws&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#s3&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cloud&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#data&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Discover Amazon S3 Metadata: A New Way to Explore Your Storage at AWS re:Invent 2024</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Wed, 04 Dec 2024 03:33:19 +0000</pubDate>
      <link>https://forem.com/aws-builders/discover-amazon-s3-metadata-a-new-way-to-explore-your-storage-at-aws-reinvent-2024-4ijn</link>
      <guid>https://forem.com/aws-builders/discover-amazon-s3-metadata-a-new-way-to-explore-your-storage-at-aws-reinvent-2024-4ijn</guid>
      <description>&lt;p&gt;Amazon Web Services (AWS) has revolutionized data storage and management once again with a groundbreaking feature introduced at AWS re:Invent 2024: &lt;strong&gt;Amazon S3 Metadata&lt;/strong&gt;. This new addition to Amazon Simple Storage Service (S3) simplifies the way we interact with and analyze the metadata of our S3 objects, empowering businesses to streamline workflows and enhance data insights. &lt;/p&gt;

&lt;p&gt;Here’s everything you need to know about this powerful new feature.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Challenge of Scale&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Organizations leveraging Amazon S3 often deal with massive datasets — billions or even trillions of objects in a single bucket. Identifying specific objects based on characteristics like size, tags, or patterns in their keys is no easy task. Historically, businesses had to build custom systems to manage and query metadata, which could be complex, hard to scale, and prone to falling out of sync with the actual data.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What is Amazon S3 Metadata?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Amazon S3 Metadata introduces &lt;strong&gt;automated metadata capture&lt;/strong&gt; for objects stored in S3 buckets. This metadata is stored in &lt;strong&gt;Apache Iceberg tables&lt;/strong&gt;, enabling compatibility with tools like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Amazon Athena&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Amazon Redshift&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Amazon QuickSight&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apache Spark&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these tools, you can perform scalable queries on metadata to find objects of interest efficiently, whether for analytics, data processing, or AI training.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Rich Metadata Elements&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The metadata schema includes over 20 elements, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bucket Name&lt;/strong&gt; and &lt;strong&gt;Object Key&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creation/Modification Time&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage Class&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encryption Details&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Object Tags&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User Metadata&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, the feature supports storing application-specific metadata in separate tables for advanced queries.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How Does It Work?&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Enable Metadata Capture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To get started, designate a bucket and table to store your metadata. Metadata updates are automatically recorded whenever objects are created, modified, or deleted. Each update includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Record Type:&lt;/strong&gt; CREATE, UPDATE, or DELETE&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sequence Number:&lt;/strong&gt; Tracks historical records&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamps:&lt;/strong&gt; Capture modification times&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%2Fwbulcwqroffsnxze7pv5.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%2Fwbulcwqroffsnxze7pv5.png" alt=" " width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Query Metadata Effortlessly&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Using Iceberg-compatible tools, query metadata to retrieve insights like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Objects uploaded within a specific timeframe&lt;/li&gt;
&lt;li&gt;Objects matching a particular tag or key pattern&lt;/li&gt;
&lt;li&gt;Size-based filters for optimizing storage costs&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  S3 Default Metadata:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;By default, S3 Metadata provides three types of metadata:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;1- System-defined metadata, such as an object's creation time and storage class&lt;/p&gt;

&lt;p&gt;2- Custom metadata, such as tags and user-defined metadata that was included during object upload&lt;/p&gt;

&lt;p&gt;3- Event metadata, such as when an object is updated or deleted, and the AWS account that made the request.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For details about what data is stored in metadata tables, see &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/metadata-tables-schema.html" rel="noopener noreferrer"&gt;S3 Metadata tables schema&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;How Metadata Tables Work&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Amazon S3 takes the reins when it comes to managing metadata tables, ensuring their accuracy and performance. Here’s what makes them stand out:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Read-Only for Integrity&lt;/strong&gt;: Metadata tables are fully managed by Amazon S3 and are read-only to all IAM principals. This guarantees they always reflect the exact state of your bucket. You can delete your metadata tables if needed, but you can't directly modify them.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Automatic Maintenance&lt;/strong&gt;: Amazon S3 periodically performs maintenance activities, such as file compaction and removal of unreferenced files. These automated processes help:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔧 Optimize query performance.
&lt;/li&gt;
&lt;li&gt;💰 Minimize storage costs for metadata tables.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Effort Required&lt;/strong&gt;: This maintenance happens automatically—no need for opt-ins or manual configurations. However, if customization is required, you have the flexibility to configure these activities.  &lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Hands-On Example&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here’s how you can enable and query metadata in a few simple steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Create a Table Bucket&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3tables create-table-bucket &lt;span class="nt"&gt;--name&lt;/span&gt; my-metadata-bucket &lt;span class="nt"&gt;--region&lt;/span&gt; us-west-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Configure Metadata Capture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Prepare a JSON configuration file:&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;"S3TablesDestination"&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;"TableBucketArn"&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:s3tables:us-west-1:123456789012:bucket/my-metadata-bucket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"TableName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my_s3_metadata_table"&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;and Attach this configuration to your data bucket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3api create-bucket-metadata-table-configuration &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bucket&lt;/span&gt; my-data-bucket &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metadata-table-configuration&lt;/span&gt; file://config.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-west-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Query Metadata&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Using Apache Spark&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spark-submit &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--packages&lt;/span&gt; org.apache.iceberg:iceberg-spark-runtime-3.4_2.12:1.6.0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--conf&lt;/span&gt; &lt;span class="s2"&gt;"spark.sql.catalog.mytablebucket=org.apache.iceberg.spark.SparkCatalog"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--conf&lt;/span&gt; &lt;span class="s2"&gt;"spark.sql.catalog.mytablebucket.warehouse=s3://my-metadata-bucket"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  query.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Why It Matters&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;With Amazon S3 Metadata, AWS eliminates the complexity of custom metadata systems. Now, you can:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enhance data discoverability for analytics and AI workloads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintain a scalable and synchronized view of your S3 objects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simplify compliance and auditing with enriched metadata tracking.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Further Resources&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;📺 &lt;strong&gt;Watch the Video Overview&lt;/strong&gt;: &lt;a href="https://www.youtube.com/watch?v=pWekT7Ic6VE" rel="noopener noreferrer"&gt;Amazon S3 Metadata at AWS re:Invent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Explore the Official Feature Page&lt;/strong&gt;: &lt;a href="https://aws.amazon.com/s3/features/metadata/" rel="noopener noreferrer"&gt;Amazon S3 Metadata&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📝 &lt;strong&gt;Read the AWS Blog Post by Jeff Barr&lt;/strong&gt;: &lt;a href="https://aws.amazon.com/blogs/aws/introducing-queryable-object-metadata-for-amazon-s3-buckets-preview/" rel="noopener noreferrer"&gt;Introducing Queryable Object Metadata for Amazon S3 Buckets&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Follow me on:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/ahmedadel333/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>s3</category>
      <category>cloud</category>
      <category>data</category>
    </item>
    <item>
      <title>Low Level Design - Logging Framework</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Fri, 17 May 2024 15:30:39 +0000</pubDate>
      <link>https://forem.com/ahmedadel/low-level-design-logging-framework-n12</link>
      <guid>https://forem.com/ahmedadel/low-level-design-logging-framework-n12</guid>
      <description>&lt;h1&gt;
  
  
  🛠️ Practicing Low-Level Design: Building a Logging Framework 📝
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Looking to enhance your low-level design skills using design patterns? In this tutorial, we'll embark on a fascinating journey of building a logging framework from the ground up. &lt;/li&gt;
&lt;li&gt;By leveraging the power of three key design patterns
&lt;strong&gt;&lt;em&gt;Singleton, Chain of Responsibility, and Observer&lt;/em&gt;&lt;/strong&gt; we'll not only create a functional logging system but also gain valuable insights into the art of low-level design. So, roll up your sleeves, fire up your favorite IDE, and let's dive into this hands-on coding adventure! 💻&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let's start with gathering the requirements ...
&lt;/h2&gt;

&lt;p&gt;1- 📌 &lt;strong&gt;Multiple Sync:&lt;/strong&gt; The framework should support logging in multiple places, such as console, log file, database, and distributed queue.&lt;br&gt;
2- 📌 &lt;strong&gt;Multiple Categories:&lt;/strong&gt; The framework should support logging into multiple categories, such as info, debug, and error.&lt;br&gt;
3- 📌 &lt;strong&gt;Configurability:&lt;/strong&gt; The category and logging location should be configurable.&lt;/p&gt;

&lt;p&gt;Here is the result code we are going to implement today &lt;br&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://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Ahmed-Adel3" rel="noopener noreferrer"&gt;
        Ahmed-Adel3
      &lt;/a&gt; / &lt;a href="https://github.com/Ahmed-Adel3/Low-Level-Design" rel="noopener noreferrer"&gt;
        Low-Level-Design
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &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;Low-Level-Design&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;Welcome to the Low-level Design Examples repository! Here, you'll find a collection of practical examples demonstrating various low-level design concepts and patterns. These examples are aimed at helping you understand and implement robust, efficient, and maintainable software solutions.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Contribute&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;We welcome contributions to this repository! If you have any low-level design examples or improvements to existing examples, feel free to open a pull request. Let's collaborate to create a valuable resource for the software development community.&lt;/p&gt;

&lt;p&gt;If you find these examples helpful, please consider starring this repository to show your support. Thank you for visiting!&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Ahmed-Adel3/Low-Level-Design" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  So our main components will be:
&lt;/h2&gt;

&lt;p&gt;📚 Logger Class: The main class exposed to the application for writing logs.&lt;br&gt;
📚 Categories: Info, Debug, and Error.&lt;br&gt;
📚 Target: Console, File, and Database.&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%2Fpqvnybafciyggpy10mkc.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%2Fpqvnybafciyggpy10mkc.png" alt=" " width="800" height="896"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Logger class:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For this class, we will start with a creational design pattern to create the logger.&lt;/li&gt;
&lt;li&gt;Here, we will choose &lt;code&gt;Singleton design&lt;/code&gt; pattern to create just one instance from the logger all over our application&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%2Fvsmcj490ysotv5ooxd9g.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%2Fvsmcj490ysotv5ooxd9g.png" alt=" " width="640" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Singleton pattern ensures that a class has only one instance and provides a global point of access to it.&lt;/span&gt;
&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Private static instance of the Logger class.&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Private constructor to prevent instantiation of the Logger class from outside.&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Check if an instance of Logger already exists, throw an exception if so.&lt;/span&gt;
        &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InvalidOperationException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Object already created"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Public static method to provide access to the single instance of the Logger class.&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="nf"&gt;GetLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Check if _logger is null (not yet initialized).&lt;/span&gt;
        &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Use locking to ensure thread safety in multi-threaded environments.&lt;/span&gt;
            &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&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="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Double-check if _logger is still null (another thread might have initialized it while waiting for the lock).&lt;/span&gt;
                &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// Create a new instance of Logger and assign it to _logger.&lt;/span&gt;
                    &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Return the single instance of Logger.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  So this implementation:
&lt;/h3&gt;

&lt;p&gt;🚫 &lt;strong&gt;Prevent Multiple Instances&lt;/strong&gt;: The private constructor prevents the creation of multiple instances of the &lt;code&gt;Logger&lt;/code&gt; class, so it's the class's responsibility to create the object and return the same instance when requested using the &lt;code&gt;GetLogger&lt;/code&gt; function.&lt;/p&gt;




&lt;h2&gt;
  
  
  Now let's move to the second section, categorization of the logs ...
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For that we will use &lt;strong&gt;&lt;em&gt;Chain of responsibility&lt;/em&gt;&lt;/strong&gt; design pattern&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Chain of Responsibility&lt;/em&gt;&lt;/strong&gt; is a behavioral design pattern that lets you pass requests along a chain of handlers. Upon receiving a request, each handler decides either to process the request or to pass it to the next handler in the chain.&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%2Faaekvhagabeetp3freci.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%2Faaekvhagabeetp3freci.png" alt=" " width="640" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's now create a simple Enum to carry the values that will identify the log level ...
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;LoggerLevel&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="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Debug&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now, let's implement the Chain of Responsibility pattern for categories (Info, Debug, and Error) using the AbstractLogger class and its concrete subclasses.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;LoggingSystem&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// AbstractLogger is an abstract base class for other logging classes.&lt;/span&gt;
    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractLogger&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Levels is a protected field that holds the logging level.&lt;/span&gt;
        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;Levels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// _nextLevelLogger is a private field that holds the next logger in the chain of responsibility.&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;_nextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// SetNextLevelLogger is a public method that sets the next logger in the chain of responsibility.&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SetNextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;nextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_nextLevelLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// LogMessage is a public method that logs a message.&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;LogMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// If the current logger's level matches the provided level, it displays the message.&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Levels&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;Display&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;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="c1"&gt;// Regardless of whether it displayed the message, it passes the message to the next logger in the chain (if there is one).&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_nextLevelLogger&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;_nextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&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;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Display is a protected abstract method that displays a message.&lt;/span&gt;
        &lt;span class="c1"&gt;// This method has no implementation in this class and must be implemented in any non-abstract subclass.&lt;/span&gt;
        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  AbstractLogger Class:
&lt;/h2&gt;

&lt;p&gt;🧩 &lt;strong&gt;Chain of Responsibility&lt;/strong&gt;: &lt;code&gt;AbstractLogger&lt;/code&gt; implements the Chain of Responsibility pattern, allowing different loggers to handle log messages based on their logging levels.&lt;/p&gt;

&lt;p&gt;🔄 &lt;strong&gt;Next Logger&lt;/strong&gt;: It maintains a private field &lt;code&gt;_nextLevelLogger&lt;/code&gt; to hold the reference to the next logger in the chain, enabling the passing of log messages to the next logger if needed.&lt;/p&gt;

&lt;p&gt;🔒 &lt;strong&gt;Levels Field&lt;/strong&gt;: The &lt;code&gt;Levels&lt;/code&gt; field holds the logging level for the current logger, determining which messages to handle.&lt;/p&gt;

&lt;p&gt;📝 &lt;strong&gt;LogMessage Method&lt;/strong&gt;: The &lt;code&gt;LogMessage&lt;/code&gt; method checks if the provided logging level matches the logger's level. If it does, it displays the message; otherwise, it passes the message to the next logger in the chain.&lt;/p&gt;

&lt;p&gt;🚧 &lt;strong&gt;Display Method&lt;/strong&gt;: The &lt;code&gt;Display&lt;/code&gt; method is a protected abstract method that must be implemented by subclasses to handle the actual display of log messages.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;SetNextLevelLogger Method&lt;/strong&gt;: This method allows setting the next logger in the chain, establishing the order in which loggers handle messages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Now let's create the concrete classes for displaying the message...
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For Info:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InfoLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;InfoLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Levels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;//temporary for now ...&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"INFO: "&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;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;ul&gt;
&lt;li&gt;For Error:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ErrorLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Levels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;//temporary for now ...&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ERROR: "&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;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;ul&gt;
&lt;li&gt;For Debug:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DebugLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;DebugLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Levels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;//temporary for now ...&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DEBUG: "&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;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;
  
  
  Now, let's edit or logger class ...
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;we need to use the abstract logger to create loggers for various levels.&lt;/li&gt;
&lt;li&gt;So we will instantiate a new instance of the abstract logger, let's name it _chainOfLogger in the GetLogger function.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;_chainOfLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InvalidOperationException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Object already created"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="nf"&gt;GetLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&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="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="n"&gt;_chainOfLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;CreateChainOfLogger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="c1"&gt;//IS THIS REALLY WHERE THE CreateChainOfLogger FUNCTION BELONGS??&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;- We should make a slight enhancement here ... CreateChainOfLogger doesn't actually belong to the logger class, it is not it's responsibility to build the chain...&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;So we will create another class called LogManager to handle it ...
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LogManager&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="nf"&gt;DoChaining&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create an InfoLogger with the Info level.&lt;/span&gt;
    &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;infoLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InfoLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&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="c1"&gt;// Create an ErrorLogger with the Error level.&lt;/span&gt;
    &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;errorLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ErrorLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a DebugLogger with the Debug level.&lt;/span&gt;
    &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;debugLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DebugLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Set the next logger for the InfoLogger to be the ErrorLogger.&lt;/span&gt;
    &lt;span class="n"&gt;infoLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetNextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errorLogger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Set the next logger for the ErrorLogger to be the DebugLogger.&lt;/span&gt;
    &lt;span class="n"&gt;errorLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetNextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debugLogger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Return the first logger in the chain (InfoLogger).&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;infoLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;🔗 Logger Chain Setup:&lt;/strong&gt; The DoChaining method sets up a chain of responsibility for loggers, where each logger handles messages based on its logging level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔄 Chain Order:&lt;/strong&gt; It creates three loggers (InfoLogger, ErrorLogger, and DebugLogger) with increasing logging levels (Info &amp;lt; Error &amp;lt; Debug) and sets the next logger in the chain accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧩 Chain Completion:&lt;/strong&gt; The InfoLogger is set to pass messages to the ErrorLogger, which in turn passes messages to the DebugLogger. This completes the chain, ensuring that log messages are handled appropriately based on their levels.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Then we will use this function to create the chain inside the Logger class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After that, we will implement a function to create the log itself, it a general function accepting the message and the level, it will also be a private function, it will only be called from inside the logger class by three functions for each log level...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;So the Logger class will be like below ...&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;_chainOfLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InvalidOperationException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Object already created"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="nf"&gt;GetLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&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="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                        &lt;span class="n"&gt;_chainOfLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LogManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DoChaining&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;CreateLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&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;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;CreateLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;CreateLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// The CreateLog method is a private method that creates a log with the provided level and message.&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;CreateLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// It calls the LogMessage method on the chain of loggers with the provided level, message, and logger target.&lt;/span&gt;
            &lt;span class="n"&gt;_chainOfLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_loggerTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Let's test our application till now, let's create a simple console app to test it ...
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;LoggingSystem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;logger&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;GetLogger&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;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This is info message"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"___"&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;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This is Error message"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"___"&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;Debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This is Debug message"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and after running it, we will have the result as below&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%2Fa0yc6d9hilwjqyklrr9m.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%2Fa0yc6d9hilwjqyklrr9m.png" alt=" " width="343" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see:&lt;br&gt;
1- Info message prints only log&lt;br&gt;
2- Error message prints info and error&lt;br&gt;
3- Debug message prints info, error, and debug.&lt;/p&gt;


&lt;h3&gt;
  
  
  Now let's move to the last part of our implementation, which is the log target, here we will be using the &lt;em&gt;&lt;strong&gt;Observer design pattern&lt;/strong&gt;&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;_Observer _&lt;/strong&gt; is a behavioral design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing.&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%2Fgfroc45z4xvso5uhmnjh.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%2Fgfroc45z4xvso5uhmnjh.png" alt=" " width="640" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, we will have two parts here ...&lt;br&gt;
 1- The target, which will be the changing part, where the log target is changing.&lt;br&gt;
 2- The constant part, which is the observer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;So Lt's create the 2 classes, first we will write an interface for all Log observers (console, file, database, ..etc).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This class will have only the log function, to force all its implementations to implement it.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ILogObserver&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Log&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&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;ul&gt;
&lt;li&gt;Now let's assume we will have console, database and file loggers ...&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And let's ignore the implementation of the logging mechanism inside each of the logging targets for now&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Console Logger&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConsoleLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ILogObserver&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Writing to Console "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;File Logger
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ILogObserver&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Writing to File "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Database Logger
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatabaseLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ILogObserver&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Writing to Database"&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Now let's implement the observer class which will contain:
&lt;/h3&gt;

&lt;p&gt;1- A list of observers.&lt;br&gt;
2- A function to add a new observer.&lt;br&gt;
3- A second method to remove an observer.&lt;br&gt;
4- A third method to notify all observers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoggerTarget&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&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;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ILogObserver&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_logObservers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&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;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ILogObserver&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;();&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;AddObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ILogObserver&lt;/span&gt; &lt;span class="n"&gt;logObserver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;_logObservers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ContainsKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;_logObservers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ILogObserver&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;_logObservers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logObserver&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;RemoveObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ILogObserver&lt;/span&gt; &lt;span class="n"&gt;logObserver&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;logObservers&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_logObservers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;logObservers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logObserver&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;NotifyAllObservers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_logObservers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ContainsKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;logObserver&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_logObservers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;logObserver&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="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="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;
  
  
  Now, where will we notify our observers ?🤔
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The Logger class of course...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Same as what we did with the chain of logger, we will instantiate Log target in the logger class in the GetLogger function using the Logger manager again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also the LoggerTarget needs to be passed to the LogMessage and Display function.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;_chainOfLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;_loggerTarget&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InvalidOperationException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Object already created"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="nf"&gt;GetLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&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="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&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="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="n"&gt;_chainOfLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LogManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DoChaining&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="n"&gt;_loggerTarget&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LogManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddObservers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;CreateLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&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;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;CreateLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;CreateLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;CreateLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_chainOfLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_loggerTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;And the LoggerManager will implement the new &lt;code&gt;AddObservers&lt;/code&gt; function as below
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LogManager&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="nf"&gt;DoChaining&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;infoLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InfoLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&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;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;errorLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ErrorLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;debugLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DebugLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;infoLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetNextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errorLogger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;errorLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetNextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debugLogger&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;infoLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// AddObservers is a static method that sets up observers for different logging levels.&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="nf"&gt;AddObservers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Create a new LoggerTarget. This is the target that the observers will be observing.&lt;/span&gt;
            &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;LoggerTarget&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// Create a new ConsoleLogger. This logger will log messages to the console.&lt;/span&gt;
            &lt;span class="n"&gt;ConsoleLogger&lt;/span&gt; &lt;span class="n"&gt;consoleLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ConsoleLogger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// Add the ConsoleLogger as an observer for Info level logs.&lt;/span&gt;
            &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&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;consoleLogger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// Add the ConsoleLogger as an observer for Error level logs.&lt;/span&gt;
            &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;consoleLogger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// Add the ConsoleLogger as an observer for Debug level logs.&lt;/span&gt;
            &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;consoleLogger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// Create a new FileLogger. This logger will log messages to a file.&lt;/span&gt;
            &lt;span class="n"&gt;FileLogger&lt;/span&gt; &lt;span class="n"&gt;fileLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FileLogger&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// Add the FileLogger as an observer for Error level logs.&lt;/span&gt;
            &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fileLogger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// Return the LoggerTarget with the observers added.&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👁️ &lt;strong&gt;Observer Setup&lt;/strong&gt;: The &lt;code&gt;AddObservers&lt;/code&gt; method sets up observers for different logging levels using the Observer design pattern. Observers watch for changes in the target (the &lt;code&gt;LoggerTarget&lt;/code&gt;) and react accordingly.&lt;/p&gt;

&lt;p&gt;📚 &lt;strong&gt;LoggerTarget Creation&lt;/strong&gt;: It creates a new &lt;code&gt;LoggerTarget&lt;/code&gt;, which serves as the target that observers will be observing. The &lt;code&gt;LoggerTarget&lt;/code&gt; manages the list of observers and notifies them of any changes.&lt;/p&gt;

&lt;p&gt;🖥️ &lt;strong&gt;ConsoleLogger Setup&lt;/strong&gt;: The method creates a &lt;code&gt;ConsoleLogger&lt;/code&gt;, which logs messages to the console. It then adds this &lt;code&gt;ConsoleLogger&lt;/code&gt; as an observer for Info, Error, and Debug level logs.&lt;/p&gt;

&lt;p&gt;📁 &lt;strong&gt;FileLogger Setup&lt;/strong&gt;: Additionally, the method creates a &lt;code&gt;FileLogger&lt;/code&gt;, which logs messages to a file. It adds this &lt;code&gt;FileLogger&lt;/code&gt; as an observer specifically for Error level logs.&lt;/p&gt;

&lt;p&gt;🔍 &lt;strong&gt;Observer Registration&lt;/strong&gt;: Observers are registered with the &lt;code&gt;LoggerTarget&lt;/code&gt; using the &lt;code&gt;AddObserver&lt;/code&gt; method, specifying the logging level they are interested in and the corresponding logger to handle messages at that level.&lt;/p&gt;

&lt;p&gt;📝 &lt;strong&gt;Return&lt;/strong&gt;: Finally, the method returns the &lt;code&gt;LoggerTarget&lt;/code&gt; with all the observers added, ready to observe and react to changes in logging levels.&lt;/p&gt;

&lt;h4&gt;
  
  
  Notice that in the Logger class, LoggerTarget is now sent to the LogMessage function, it will be passed to the display function for each type of logger (Debug, info, or error) to notify its observers.
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;So, let's edit the Abstract Logger too, to be like below
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractLogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;Levels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;_nextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SetNextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AbstractLogger&lt;/span&gt; &lt;span class="n"&gt;nextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_nextLevelLogger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;LogMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Levels&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Display&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;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_nextLevelLogger&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_nextLevelLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&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;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&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;ul&gt;
&lt;li&gt;&lt;p&gt;Now let's edit all implementations of the Display function..&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Info Logger&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InfoLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;InfoLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Levels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//replace console log with notify observer &lt;/span&gt;
        &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotifyAllObservers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&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="s"&gt;"INFO: "&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;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;ul&gt;
&lt;li&gt;Error Logger
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ErrorLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Levels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;levels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//replace console log with notify observer&lt;/span&gt;
        &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotifyAllObservers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ERROR: "&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;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;ul&gt;
&lt;li&gt;Debug Logger
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DebugLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AbstractLogger&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;DebugLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Levels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Display&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="c1"&gt;//replace console log with notify observer&lt;/span&gt;
             &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotifyAllObservers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"DEBUG: "&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;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;ul&gt;
&lt;li&gt;let's run the solution now and check the result ...&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%2Fh4adflgah9nqqrghp50h.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%2Fh4adflgah9nqqrghp50h.png" alt=" " width="413" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And it's working as expected, because according to our configuration, we are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;printing info message to console&lt;/li&gt;
&lt;li&gt;printing error message in console and file (and I will be printed in error and info levels).&lt;/li&gt;
&lt;li&gt;printing debug message in console and file (and I will be printed in error,info and debug levels).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  and we can easily change this behavior...
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Let's assume we only need to print in the same level as instructed, not the level and the levels below it, then in the LogMessage function, we can easily edit it like below
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;LogMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoggerLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoggerTarget&lt;/span&gt; &lt;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;//old: if (Levels &amp;lt;= level)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Levels&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;Display&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;span class="n"&gt;loggerTarget&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="c1"&gt;//The rest of the code of Abstract logger&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now the result will be &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%2Fr9kl2bne746ssqxr6njd.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%2Fr9kl2bne746ssqxr6njd.png" alt=" " width="461" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  So as instructed in the LoggerManager class :
&lt;/h4&gt;

&lt;p&gt;1- Console Logger will have info, debug and error.&lt;br&gt;
2- File logger will have only errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Of course this LoggerManager in a real logger system will read from a config file to give you the flexibility to change logging levels and targets.
&lt;/h3&gt;




&lt;h1&gt;
  
  
  Wrapping Up: Embracing the Power of Design Patterns in Logging
&lt;/h1&gt;

&lt;p&gt;In this tutorial, we've explored the intricate world of low-level design by building a logging framework from scratch. We've delved into the Singleton pattern, ensuring our logging class has only one instance, and the Chain of Responsibility pattern, allowing different loggers to handle log messages based on their levels. We've also embraced the Observer pattern, setting up observers to react to changes in logging levels.&lt;/p&gt;

&lt;p&gt;By understanding and implementing these design patterns, we've not only created a functional logging system but also gained valuable insights into the art of designing flexible, extensible, and maintainable software solutions. We hope this tutorial has inspired you to apply these principles in your own projects and continue to explore the vast landscape of software design patterns. Happy coding!&lt;/p&gt;

&lt;p&gt;Follow me on:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/ahmedadel333/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>systemdesign</category>
      <category>logging</category>
      <category>oop</category>
    </item>
    <item>
      <title>Mountpoint for Amazon S3 is now generally available and ready for production workloads 🚀</title>
      <dc:creator>Ahmed Adel</dc:creator>
      <pubDate>Wed, 09 Aug 2023 20:25:50 +0000</pubDate>
      <link>https://forem.com/aws-builders/mountpoint-for-amazon-s3-is-now-generally-available-and-ready-for-production-workloads-1kdl</link>
      <guid>https://forem.com/aws-builders/mountpoint-for-amazon-s3-is-now-generally-available-and-ready-for-production-workloads-1kdl</guid>
      <description>&lt;h1&gt;
  
  
  AWS Mountpoint: A High-Performance File Client for Amazon S3
&lt;/h1&gt;

&lt;p&gt;Today, AWS announces the general availability of Mountpoint for Amazon S3.&lt;/p&gt;

&lt;p&gt;➥ AWS Mountpoint is an open source file client that makes it easy for Linux-based applications to connect directly to Amazon Simple Storage Service (Amazon S3) buckets and access objects using file APIs. It is ideal for large-scale analytics applications that read and generate large amounts of S3 data in parallel, but don't require the ability to write to the middle of existing objects.&lt;/p&gt;

&lt;p&gt;➥ It automatically translates local file system API calls to REST API calls on S3 objects. Mountpoint for Amazon S3 is optimized for high-throughput performance. It builds on the AWS Common Runtime (CRT) library, which is purpose-built for high performance and low-resource usage to make efficient use of your compute resources.&lt;/p&gt;

&lt;p&gt;It is a powerful tool that can be used to accelerate a variety of workloads, including:&lt;/p&gt;

&lt;p&gt;✏️ Data lakes.&lt;br&gt;
✏️ Machine learning training.&lt;br&gt;
✏️ Image rendering.&lt;br&gt;
✏️ Autonomous vehicle simulation.&lt;br&gt;
✏️ Extract, transform, and load (ETL) processes.&lt;/p&gt;


&lt;h2&gt;
  
  
  ➽ Here are some of the key benefits of AWS Mountpoint:
&lt;/h2&gt;

&lt;p&gt;✅ High throughput:&lt;/p&gt;

&lt;p&gt;AWS Mountpoint can achieve up to 100 GB/s of throughput on a single EC2 instance, and can scale to support even higher throughput requirements.&lt;/p&gt;

&lt;p&gt;✅ Low latency:&lt;/p&gt;

&lt;p&gt;AWS Mountpoint has very low latency, making it ideal for latency-sensitive applications.&lt;/p&gt;

&lt;p&gt;✅ Elasticity:&lt;/p&gt;

&lt;p&gt;AWS Mountpoint is fully elastic, so you can scale up or down your throughput requirements as needed.&lt;/p&gt;

&lt;p&gt;✅ Cost-effectiveness:&lt;/p&gt;

&lt;p&gt;AWS Mountpoint is a cost-effective way to access your data in Amazon S3. You only pay for the storage and bandwidth that you use.&lt;/p&gt;



&lt;p&gt;Watch &lt;a href="https://www.linkedin.com/in/devabrat-kumar/" rel="noopener noreferrer"&gt;Devabrat Kumar&lt;/a&gt; - Senior Technical product leader at AWS talks about it  : &lt;iframe width="710" height="399" src="https://www.youtube.com/embed/EYmtpzVZ0BU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting started:
&lt;/h2&gt;

&lt;p&gt;➥ Run these two commands to install Mountpoint for Amazon S3 on your Amazon Linux EC2 instance (for Graviton instances, replace x86_64 with arm64 in the URL):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://s3.amazonaws.com/mountpoint-s3-release/latest/x86_64/mount-s3.rpm
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; ./mount-s3.rpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Ubuntu, use these commands instead (for Graviton instances, replace x86_64 with arm64 in the URL):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wget https://s3.amazonaws.com/mountpoint-s3-release/latest/x86_64/mount-s3.deb
sudo apt-get install -y ./mount-s3.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://github.com/awslabs/mountpoint-s3/blob/main/doc/INSTALL.md" rel="noopener noreferrer"&gt;Installing Mountpoint for Amazon S3&lt;/a&gt; for detailed instructions and other installation options (including Docker or building from source).&lt;/p&gt;

&lt;p&gt;➥ Once you've got Mountpoint for Amazon S3 installed, you can mount your Amazon S3 bucket. You'll need valid AWS credentials to access your bucket; for example, Mountpoint will automatically use credentials from an IAM role associated with your EC2 instance, or you can use the &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; environment variables.&lt;/p&gt;

&lt;p&gt;➥ To mount your bucket, run this command, replacing &lt;code&gt;DOC-EXAMPLE-BUCKET&lt;/code&gt; with the &lt;strong&gt;name of your bucket&lt;/strong&gt; and &lt;code&gt;/path/to/mount&lt;/code&gt; with the &lt;strong&gt;directory you want to mount the bucket to&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;mount-s3 DOC-EXAMPLE-BUCKET /path/to/mount
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can work with your bucket contents as if they were a local file system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls /path/to/mount
echo "Hello World!" &amp;gt; /path/to/mount/Data.txt
cat /path/to/mount/Data.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you're finished accessing your bucket, you can unmount it (you might need sudo):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;umount /path/to/mount
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://github.com/awslabs/mountpoint-s3/blob/main/doc/CONFIGURATION.md" rel="noopener noreferrer"&gt;Configuring Mountpoint for Amazon S3&lt;/a&gt; for more details on how to configure and use Mountpoint, including options for providing AWS credentials.&lt;/p&gt;




&lt;p&gt;To learn more about AWS Mountpoint, please visit the following resources:&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/mountpoint.html" rel="noopener noreferrer"&gt;AWS Mountpoint documentation&lt;/a&gt;&lt;br&gt;
🌐 &lt;a href="https://github.com/awslabs/mountpoint-s3" rel="noopener noreferrer"&gt;AWS Mountpoint GitHub repository&lt;/a&gt;&lt;br&gt;
🌐 &lt;a href="https://aws.amazon.com/blogs/aws/mountpoint-for-amazon-s3-generally-available-and-ready-for-production-workloads/" rel="noopener noreferrer"&gt;Mountpoint for Amazon S3&lt;/a&gt;&lt;br&gt;
by &lt;a href="https://www.linkedin.com/in/jeffbarr/" rel="noopener noreferrer"&gt;Jeff Barr&lt;/a&gt; - Vice President &amp;amp; Chief Evangelist of Amazon Web Services&lt;br&gt;
🌐 &lt;a href="https://aws.amazon.com/s3/features/mountpoint/" rel="noopener noreferrer"&gt;Mountpoint service page&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I hope this article was helpful! If you have any questions, please feel free to leave a comment below.&lt;/p&gt;

&lt;p&gt;Follow me on:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/ahmedadel333/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>amazon</category>
      <category>cloud</category>
      <category>aws</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
