<?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: Peter Diakov</title>
    <description>The latest articles on Forem by Peter Diakov (@peter_dyakov_06f3c69a46b7).</description>
    <link>https://forem.com/peter_dyakov_06f3c69a46b7</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%2F2075891%2Fc4992686-21c1-475f-859d-b1949507f646.jpg</url>
      <title>Forem: Peter Diakov</title>
      <link>https://forem.com/peter_dyakov_06f3c69a46b7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/peter_dyakov_06f3c69a46b7"/>
    <language>en</language>
    <item>
      <title>CloudFront: Where You Lose Money</title>
      <dc:creator>Peter Diakov</dc:creator>
      <pubDate>Tue, 23 Dec 2025 20:02:41 +0000</pubDate>
      <link>https://forem.com/peter_dyakov_06f3c69a46b7/cloudfront-where-you-lose-money-2kam</link>
      <guid>https://forem.com/peter_dyakov_06f3c69a46b7/cloudfront-where-you-lose-money-2kam</guid>
      <description>&lt;p&gt;CloudFront is usually added to an architecture with good intentions: performance, reliability, lower origin load.Then, months later, it shows up near the top of the AWS bill and nobody is sure why.&lt;br&gt;
The uncomfortable truth is that CloudFront rarely becomes expensive because of one big mistake.It becomes expensive because it &lt;em&gt;amplifies small inefficiencies at scale&lt;/em&gt;.&lt;br&gt;
Here are the places where CloudFront quietly burns money and what to look at first.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Caching is not a checkbox&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most CloudFront cost problems start with caching that exists, but isn’t designed.&lt;br&gt;
Different types of content behave very differently, yet they’re often served under the same cache policy. Immutable static assets, frequently changing HTML, and API responses all deserve different treatment.&lt;br&gt;
Files with unique names (especially hashed assets) should be cached aggressively. If the filename changes on every build, the file itself is effectively immutable. Revalidating it every few minutes is pure waste.&lt;br&gt;
At the same time, content like &lt;code&gt;index.html&lt;/code&gt; does change but disabling caching entirely is rarely the right answer. A short TTL is usually enough to balance freshness and cost.&lt;br&gt;
Once CloudFront caching is reasonable, browser caching becomes the next win. Proper &lt;code&gt;Cache-Control&lt;/code&gt; headers on S3 objects reduce repeated requests and quietly cut costs without touching infrastructure.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;If CloudFront isn’t the only entry point, you’re overpaying&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When content is downloaded directly from S3 instead of passing through CloudFront, you don’t just lose money - you also lose security.&lt;br&gt;
This usually happens when an application accidentally exposes raw S3 URLs or when old links still point to the bucket. From a user perspective everything still works, but behind the scenes S3 is serving traffic that CloudFront should be handling.&lt;br&gt;
Financially, this bypass means: no caching and compression -&amp;gt; Higher S3 data transfer costs. But the bigger issue is &lt;em&gt;security&lt;/em&gt;.&lt;br&gt;
An S3 bucket that’s accessible to the public or reachable directly from the internet is a misconfiguration. In production, S3 should only serve content through CloudFront, enforced by &lt;em&gt;Origin Access Control&lt;/em&gt; (OAC).&lt;br&gt;
When OAC is configured, CloudFront becomes the only trusted entry point. Everything else gets blocked.&lt;br&gt;
If users — or bots — can reach S3 directly, you're both overspending and exposing your storage layer to unnecessary risk.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Compression is either on - or you’re paying for air&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Compression issues are easy to miss because they don’t break functionality.&lt;br&gt;
Some clients and third-party tools send headers that explicitly disable compression. If your origin respects those headers, responses are delivered uncompressed, increasing payload size and data transfer cost.&lt;br&gt;
CloudFront can handle compression safely but only if automatic compression is enabled. This one setting can be the difference between a reasonable bill and a confusing one.&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%2Fff8poloum5xgxybk1m6w.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%2Fff8poloum5xgxybk1m6w.png" alt=" " width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Zombie distributions still cost real money&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;CloudFront distributions tend to accumulate.&lt;br&gt;
Proof-of-concepts, temporary domains, legacy projects - they’re rarely deleted. Even if nobody uses them intentionally, bots often do.&lt;br&gt;
A quick review of distributions and their traffic metrics often reveals “ghost” resources that should have been disabled months ago. Disable first, delete later.&lt;br&gt;
Unused infrastructure that still receives traffic is pure waste.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Global CDN for a local product = wasted budget&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By default, CloudFront serves content from edge locations worldwide.&lt;br&gt;
If your users are primarily in one region, limiting the distribution to an appropriate price class can reduce data transfer costs without affecting real users. Many teams never revisit this setting after initial setup.&lt;br&gt;
Global reach is powerful but unnecessary reach is expensive.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Security rules also show up on the bill&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AWS WAF protects CloudFront, but it also evaluates rules on every request.&lt;br&gt;
Over time, rule sets grow. Managed rules are enabled “just in case”, logging is turned on for everything, and requests that should be blocked early continue through the system.&lt;br&gt;
Regular WAF reviews reduce unnecessary processing and lower CloudFront costs at the same time. Security and cost optimization are not opposites here.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Every extra kilobyte is multiplied by traffic&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even with perfect caching, CloudFront charges for data transferred.&lt;br&gt;
This is where developers matter most. It’s worth reviewing what the client actually receives, especially on the initial page load. Many applications return configuration data, metadata, or API fields that the frontend no longer uses.&lt;br&gt;
Every extra kilobyte is multiplied by traffic volume. Compression helps, but it doesn’t make unnecessary data free.&lt;br&gt;
Reducing payload size improves performance, lowers CloudFront costs, and reduces origin load without touching infrastructure.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;You can’t optimize what you don’t monitor&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;CloudFront rarely becomes expensive overnight. Costs usually drift upward quietly.&lt;br&gt;
Cost anomaly detection, monthly cost reports, and distribution-level monitoring turn CloudFront from a surprise into a controlled system. Without visibility, even good architectures decay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;CloudFront doesn’t waste your money. It &lt;em&gt;accurately bills you for inefficiency&lt;/em&gt;.&lt;br&gt;
Every missed cache opportunity, every extra header, every forgotten distribution is multiplied by traffic. Treat CloudFront as a living system (not a one-time setup) and it will stay cheap and predictable.&lt;/p&gt;

</description>
      <category>cdn</category>
      <category>aws</category>
      <category>finops</category>
      <category>devops</category>
    </item>
    <item>
      <title>CPU Limits in Kubernetes: Mostly Harmful, Occasionally Essential</title>
      <dc:creator>Peter Diakov</dc:creator>
      <pubDate>Sat, 20 Dec 2025 09:01:32 +0000</pubDate>
      <link>https://forem.com/peter_dyakov_06f3c69a46b7/cpu-limits-in-kubernetes-mostly-harmful-occasionally-essential-3i56</link>
      <guid>https://forem.com/peter_dyakov_06f3c69a46b7/cpu-limits-in-kubernetes-mostly-harmful-occasionally-essential-3i56</guid>
      <description>&lt;p&gt;CPU limits in Kubernetes are often treated as a mandatory best practice. Define requests, define limits, move on.&lt;br&gt;
Over time, however, many teams discover that CPU limits, especially for application workloads, introduce more problems than they solve.&lt;/p&gt;

&lt;p&gt;In this article, I’ll explain &lt;strong&gt;why CPU limits are frequently counterproductive&lt;/strong&gt;, and then describe a real production incident where &lt;strong&gt;the absence of CPU limits on a specific type of workload led to a node failure&lt;/strong&gt;. The takeaway is not a reversal of the original idea, but a clearer understanding of where it applies and where it absolutely does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why CPU Limits Often Hurt More Than They Help
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CPU Limits Introduce Artificial Throttling&lt;/strong&gt;&lt;br&gt;
In Kubernetes, CPU limits are enforced by the Linux scheduler using cgroups. Once a container reaches its assigned quota, it is forcibly throttled within the current scheduling period, even if the node has idle CPU capacity available.&lt;br&gt;
For workloads with bursty CPU patterns, this behavior is harmful. Many services occasionally need short-lived CPU spikes to complete work efficiently: handling request bursts, warming caches, or performing runtime maintenance tasks. When limits are set, those spikes turn into throttling events, increasing request latency and amplifying tail delays.&lt;br&gt;
In practice, this often means worse performance on an otherwise healthy and underutilized node.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Removing CPU Limits Can Improve Real-World Stability&lt;/strong&gt;&lt;br&gt;
In several production environments, removing CPU limits from application workloads has led to measurable improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lower latency under load&lt;/li&gt;
&lt;li&gt;Faster recovery from traffic spikes&lt;/li&gt;
&lt;li&gt;Reduced throttling without additional infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Autoscaling mechanisms such as HPA work best when containers can fully utilize available CPU. Artificial caps interfere with this feedback loop and delay scale-out exactly when it’s most needed.&lt;br&gt;
For many application services, CPU limits end up solving a problem that doesn’t exist, while creating one that does.&lt;/p&gt;

&lt;h2&gt;
  
  
  When This Approach Becomes Dangerous
&lt;/h2&gt;

&lt;p&gt;The guidance above assumes one critical condition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The workload must fully respect Kubernetes resource isolation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not all workloads do.&lt;br&gt;
We encountered this firsthand in a Kubernetes management cluster running build agents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Incident: Node CPU Saturation and NotReady State&lt;/strong&gt;&lt;br&gt;
A worker node suddenly reached near-constant 100% CPU utilization and remained there for several minutes. Shortly after:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The kubelet stopped reporting heartbeats&lt;/li&gt;
&lt;li&gt;The node transitioned to NotReady&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the same time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pod-level CPU metrics looked normal&lt;/li&gt;
&lt;li&gt;No throttling was visible at the pod level&lt;/li&gt;
&lt;li&gt;Nothing appeared obviously misconfigured&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The build agent pod running on the node &lt;strong&gt;did not have CPU limits configured by design&lt;/strong&gt;, following the “no CPU limits” philosophy.&lt;br&gt;
So why did a single pod manage to destabilize the entire node?&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%2Fdsj985rw4va5vp8l2uac.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%2Fdsj985rw4va5vp8l2uac.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Root Cause: Privileged Build Workloads Bypass Assumptions
&lt;/h2&gt;

&lt;p&gt;The build agent was running as a privileged pod and started its own container runtime internally to execute jobs.&lt;br&gt;
This distinction matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Actually Happened&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The pod itself was scheduled normally and respected its CPU request&lt;/li&gt;
&lt;li&gt;Inside the pod, a container runtime launched additional processes&lt;/li&gt;
&lt;li&gt;Those processes were not constrained by pod-level CPU isolation&lt;/li&gt;
&lt;li&gt;Under heavy workload, they consumed all available node CPU&lt;/li&gt;
&lt;li&gt;The kubelet was starved of CPU time&lt;/li&gt;
&lt;li&gt;Node health checks failed, and the node became &lt;code&gt;NotReady&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This was not a bug in Kubernetes. It was a mismatch between &lt;strong&gt;assumed isolation&lt;/strong&gt; and &lt;strong&gt;actual workload&lt;/strong&gt; behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Revisiting the Question: Should CPU Limits Be Used?&lt;/strong&gt;&lt;br&gt;
The correct answer is neither “always” nor “never”.&lt;br&gt;
CPU Limits Are Often Unnecessary For:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stateless application services&lt;/li&gt;
&lt;li&gt;Non-privileged containers&lt;/li&gt;
&lt;li&gt;Workloads without nested runtimes&lt;/li&gt;
&lt;li&gt;Large nodes with sufficient headroom&lt;/li&gt;
&lt;li&gt;Services managed by HPA&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CPU Limits or Strong Isolation Are Required For:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build agents and CI runners&lt;/li&gt;
&lt;li&gt;Privileged pods&lt;/li&gt;
&lt;li&gt;Workloads executing untrusted or user-defined code&lt;/li&gt;
&lt;li&gt;Nested container runtimes&lt;/li&gt;
&lt;li&gt;Small or mixed-purpose nodes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In these cases, assuming that “CPU limits are harmful” without additional isolation is a mistake.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical Recommendations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For build and CI workloads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use dedicated node groups&lt;/li&gt;
&lt;li&gt;Apply taints and tolerations&lt;/li&gt;
&lt;li&gt;Avoid colocating them with application workloads&lt;/li&gt;
&lt;li&gt;Enforce resource boundaries at the node level&lt;/li&gt;
&lt;li&gt;Prefer architectures that avoid nested runtimes&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Removing CPU limits can significantly improve performance but only when workloads behave as expected and respect Kubernetes isolation boundaries.&lt;br&gt;
Privileged workloads and build systems operate under different rules. Applying application-level best practices to them without adjustment can destabilize the entire cluster.&lt;/p&gt;

&lt;p&gt;The real lesson is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Optimize trusted workloads. Isolate the rest.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>sre</category>
      <category>performance</category>
    </item>
    <item>
      <title>Claude Skills + MCP Server: Create Consistent AWS Cost Reports in Minutes</title>
      <dc:creator>Peter Diakov</dc:creator>
      <pubDate>Sat, 13 Dec 2025 09:43:32 +0000</pubDate>
      <link>https://forem.com/peter_dyakov_06f3c69a46b7/claude-skills-mcp-server-create-consistent-aws-cost-reports-in-minutes-322f</link>
      <guid>https://forem.com/peter_dyakov_06f3c69a46b7/claude-skills-mcp-server-create-consistent-aws-cost-reports-in-minutes-322f</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This article can be useful for FinOps engineers who want to automate their monthly cost reporting workflow. FinOps is all about managing cloud costs efficiently, but creating consistent executive reports every month is time-consuming and error-prone. Most companies spend heavily on cloud infrastructure, and CTOs need clear, standardized reports to track spending trends. As a FinOps engineer, you need a system that generates professional cost reports with the same structure every month - not ad-hoc prompts that vary in quality. In this article, I’ll show you how to build a Claude Skill that combines MCP Server with AWS Cost Explorer to create deterministic, executive-ready cost reports in just 3 minutes. Once configured, you’ll never need to generate complex prompts again.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is MCP Server?
&lt;/h2&gt;

&lt;p&gt;MCP (Model Context Protocol) Server is a technology that allows AI assistants like Claude to connect directly to external tools and data sources. Think of it as a bridge between Claude and your cloud infrastructure.&lt;br&gt;
In our case, the AWS Cost Explorer MCP Server enables Claude to make API calls to AWS Cost Explorer, fetch your actual spending data, analyze usage patterns, and retrieve detailed cost breakdowns - all in real-time. Without MCP, you’d need to manually export cost data from AWS, format it, and paste it into Claude. With MCP, Claude accesses the data directly and automatically.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Are Claude Skills?
&lt;/h2&gt;

&lt;p&gt;Think of Claude Skills as reusable expert templates. Instead of explaining your requirements every single time, you create a skill file that contains all your instructions, preferences, and guidelines. Claude then follows this “playbook” perfectly every time you invoke it.&lt;br&gt;
For FinOps reporting, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same professional structure every month&lt;/li&gt;
&lt;li&gt;Consistent analysis framework&lt;/li&gt;
&lt;li&gt;No forgotten requirements&lt;/li&gt;
&lt;li&gt;Executive-ready format guaranteed&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Prerequisites for Claude Skill Creation
&lt;/h2&gt;

&lt;p&gt;Before creating the skill, you need to set up the necessary tools and permissions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install Claude Desktop - Download and install from claude.ai/download&lt;/li&gt;
&lt;li&gt;Add AWS Cost Explorer MCP Server - Configure the MCP server in your Claude Desktop settings by adding it to your configuration file&lt;/li&gt;
&lt;li&gt;Configure AWS IAM Permissions - Create an IAM user with Cost Explorer read permissions and configure the credentials&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Detailed setup instructions for the MCP server and IAM configuration can be found in the &lt;a href="https://awslabs.github.io/mcp/servers/cost-explorer-mcp-server" rel="noopener noreferrer"&gt;AWS Cost Explorer MCP Server documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating an AWS Cost Report Skill
&lt;/h2&gt;

&lt;p&gt;Creating a Claude Skill is straightforward. You simply ask Claude: “Help me create a skill for generating monthly AWS cost reports.”&lt;br&gt;
Claude will then guide you through a series of clarifying questions to understand your specific requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What data sources and tools you’re using&lt;/li&gt;
&lt;li&gt;How you organize your infrastructure (tags, environments)&lt;/li&gt;
&lt;li&gt;What report structure your executives expect&lt;/li&gt;
&lt;li&gt;What level of detail and visualizations you need&lt;/li&gt;
&lt;li&gt;What analysis and recommendations should be included&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on your answers, Claude automatically generates a skill file containing detailed, structured instructions. This file defines exactly how Claude should fetch data, analyze it, generate visualizations, and format the final report.&lt;/p&gt;

&lt;p&gt;Once the skill is created and saved in Claude Desktop, using it is incredibly simple. Just print this command in Claude prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use the AWS Cost CEO Report skill to compare November and December 2025 costs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s it. Claude follows the instructions in the skill file and delivers a consistent, professional report every time.&lt;/p&gt;

&lt;p&gt;Here is an example of Claude Skill reference file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# AWS Cost CEO Report Skill - Quick Reference


## 🚀 Quick Start

AWS cost report for the CEO - September vs October 2025

## ✅ Prerequisites Checklist
- [ ] All Cost Explorer MCP servers are started
- [ ] You have cost data for the months you want to compare


## 🎯 Trigger Phrases
| What to Say | What It Does |
|-------------|--------------|
| "AWS cost report for the CEO" | Generates full report for all accounts |
| "Compare September vs October 2025" | Month-to-month comparison |
| "Production account only" | Limits to single account |
| "We implemented VPC endpoints..." | Includes savings actions analysis |


## 📊 Report Includes
✅ Executive summary with key metrics 
✅ Visual charts and graphs 
✅ Per-account breakdowns 
✅ Cost driver analysis 
✅ Optimization recommendations 
✅ PDF export capability 


## 🎨 Report Filters
- Shows only services with &amp;gt;$50/month spend
- Analyzes services with &amp;gt;10% change OR &amp;gt;$100 change
- Focuses on top cost drivers


## 💡 Pro Tips

1. **Monthly Cadence**: Generate reports at the end of each month
2. **Include Context**: Mention infrastructure changes or savings actions
3. **Review Trends**: Look for unexpected cost increases
4. **Act on Recommendations**: Review the optimization section
5. **Export PDF**: Use browser print function to save as PDF


## 🚨 Common Issues

| Issue | Solution |
|-------|----------|
| MCP servers not accessible | Start Docker Desktop and MCP containers |
| Invalid month format | Use "September 2025" not "9/2025" |
| No data returned | Check dates aren't in future |


## 📈 Cost Optimization Areas Analyzed
- EC2 instance rightsizing
- NAT Gateway optimization (VPC endpoints)
- Data transfer costs
- Idle resources
- Over-provisioned infrastructure
- Development environment scheduling
- Storage lifecycle policies
- Reserved Instance opportunities


## 🎓 Example Requests

**Basic Report:**
Generate AWS cost report for the CEO comparing September vs October 2025

**With Savings Context:**
AWS cost report for September vs October 2025.

Actions taken:
- Implemented VPC endpoints
- Migrated to Graviton instances
- Enabled S3 Intelligent Tiering

## 📦 Skill Components
- Main workflow instructions (SKILL.md)
- MCP usage patterns (references/mcp-usage.md)
- Report structure guide (references/report-structure.md)
- HTML template reference (scripts/generate_report.py)


## 🔍 Analysis Depth
**Level 1**: Service-level cost comparison 
**Level 2**: Usage-type breakdown (instance types, hours) 
**Level 3**: Root cause identification 
**Level 4**: Contextual analysis with recommendations 


## 💰 Cost Leak Detection
The skill automatically flags:
- Unexpected spikes &amp;gt;20%
- High data transfer costs
- NAT Gateway optimization opportunities
- Idle resources
- Over-provisioned instances
- 24/7 dev/test environments
- Legacy unused resources

## 📄 Export to PDF
1. Open artifact in new window
2. Press Ctrl+P (or Cmd+P on Mac)
3. Select "Save as PDF"
4. Adjust settings if needed
5. Save and share!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits for FinOps Teams:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Reproducibility: Same report quality every month&lt;/li&gt;
&lt;li&gt;Scalability: Easy to generate reports for multiple accounts/regions&lt;/li&gt;
&lt;li&gt;Compliance: Standardized format satisfies audit requirements&lt;/li&gt;
&lt;li&gt;Onboarding: New team members can generate reports without training&lt;/li&gt;
&lt;li&gt;Evolution: Update the skill once to improve all future reports&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;MCP Server combined with Claude Skills transforms FinOps reporting from a day-long manual process into a 3-minute automated workflow. You get the speed of AI-powered analysis with the consistency and professionalism that executive leadership demands.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>finops</category>
      <category>ai</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Scalable Multi-Tenant Architecture for Hundreds of Custom Domains</title>
      <dc:creator>Peter Diakov</dc:creator>
      <pubDate>Sat, 22 Nov 2025 15:14:19 +0000</pubDate>
      <link>https://forem.com/peter_dyakov_06f3c69a46b7/scalable-multi-tenant-architecture-for-hundreds-of-custom-domains-56mn</link>
      <guid>https://forem.com/peter_dyakov_06f3c69a46b7/scalable-multi-tenant-architecture-for-hundreds-of-custom-domains-56mn</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Modern SaaS commerce platforms often face a similar challenge: supporting a large number of customer-specific storefronts, each with its own custom domain, while still relying on a shared backend. When your infrastructure is built on EKS with CloudFront and an Application Load Balancer in front, and each tenant requires its own SSL certificate, scaling becomes a real architectural puzzle.&lt;/p&gt;

&lt;p&gt;This article describes the problem we encountered, the options we evaluated, and the architecture we ultimately implemented to handle hundreds of HTTPS-enabled custom domains cleanly and reliably.&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%2Fpx5jazrczjrjugywffs0.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%2Fpx5jazrczjrjugywffs0.png" alt=" " width="598" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Context: The Multi-Tenant Storefront Platform
&lt;/h2&gt;

&lt;p&gt;Our platform allows customers to create online shops under their own domains. Dozens or even hundreds of domains like: &lt;em&gt;storeABC.com&lt;/em&gt;, &lt;em&gt;brandshop.net&lt;/em&gt;, or &lt;em&gt;my-boutique.co.uk&lt;/em&gt; - all point to a shared CloudFront distribution and eventually arrive at the same ALB and EKS cluster. The backend determines the tenant based on the incoming Host header.&lt;/p&gt;

&lt;p&gt;For this to work securely, each domain needs its own HTTPS certificate. CloudFront now supports a Multi-Tenant SaaS distribution model, which makes onboarding new domains dramatically easier: certificates are created in us-east-1, automatically validated, and attached to a single shared CloudFront distribution that serves all tenants. Also AWS ssl certificate limit is 2000 per one Multi-Tenant SaaS distribution and we can have several such distributions.&lt;/p&gt;

&lt;p&gt;This simplicity stops at CloudFront. The real challenge appears on the origin side.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Certificate Problem on the ALB Side
&lt;/h2&gt;

&lt;p&gt;CloudFront terminates HTTPS at the edge. After that, it connects to the origin - in our case, an Application Load Balancer - using HTTPS again, so  ALB also needs certificates for tls handshake. &lt;/p&gt;

&lt;p&gt;In AWS ALB has a strict quota:&lt;br&gt;
&lt;strong&gt;→ 100 SSL certificates per ALB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a system with 300+ custom domains, this limit becomes a blocker. This brings us to the architectural decision point.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture Options We Considered
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Using CloudFront VPC Origin to Avoid SSL on the ALB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the first ideas was to place CloudFront’s origin inside the VPC using the VPC Origin feature. Traffic would travel over AWS’s private network and could therefore be sent to the ALB over plain HTTP, eliminating the need for certificates on the ALB entirely. It’s elegant—until you discover that VPC Origin does not support WebSockets, a requirement for our application. That limitation alone ruled out this approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Splitting Tenants Across Multiple ALBs and Distributions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another possibility involved spliting tenants across Several CloudFront SaaS distributions and Several ALBs.This bypasses the 100-cert limit by distributing certificates across multiple ALBs and CloudFront distributions.&lt;/p&gt;

&lt;p&gt;Why we rejected it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Massive IaC overhead&lt;/li&gt;
&lt;li&gt;Requires tracking which tenant belongs to which ALB &amp;amp; distribution&lt;/li&gt;
&lt;li&gt;Complicated domain lifecycle management&lt;/li&gt;
&lt;li&gt;Harder observability &amp;amp; error tracing&lt;/li&gt;
&lt;li&gt;High risk of misconfiguration&lt;/li&gt;
&lt;li&gt;Poor maintainability at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technically feasible - but operationally a nightmare.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution: One ALB, One Distribution, One Internal Certificate
&lt;/h2&gt;

&lt;p&gt;What ultimately made this architecture scalable was realizing that CloudFront does not require the same domain that the customer is visiting to be used as the origin domain. CloudFront only expects that the origin domain configured in the distribution has a valid certificate on the ALB—nothing more. At the same time, CloudFront is perfectly capable of forwarding the original Host header to the backend.&lt;/p&gt;

&lt;p&gt;This allowed us to decouple tenant domains from the ALB entirely.&lt;/p&gt;

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

&lt;p&gt;We introduced a single internal domain, for example:&lt;br&gt;
&lt;code&gt;origin.example.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This domain points to the ALB’s DNS name via a CNAME record. The ALB holds just one TLS certificate for this internal domain, and CloudFront uses this domain as its sole origin for all tenants.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User → https://storeABC.com
 ↓
CloudFront (receives request)
- TLS handshake with storeABC.com
- Decrypts request
- Forwards request to origin
 ↓
CloudFront → Origin (ALB via CNAME):
- New HTTPS request to https://origin.example.com
- TLS handshake with ALB (*.example.com)
- Sends HTTP request with Host: storeABC.com
 ↓
ALB:
- Terminates TLS
- Receives Host: storeABC.com
- Forwards to backend service/pod in EKS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup, the number of tenant domains no longer affects the ALB at all. Scaling from 10 to 1,000 custom domains is simply a matter of attaching more certificates to CloudFront, which is designed for that scale.&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%2Fisoeekstc5ik4cfpxn6f.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%2Fisoeekstc5ik4cfpxn6f.png" alt=" " width="717" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Architecture Works Well
&lt;/h2&gt;

&lt;p&gt;This solution eliminates the ALB certificate quota entirely while preserving strong end-to-end encryption. It keeps the infrastructure clean: only one CloudFront distribution, one ALB, one certificate on the origin, and no complicated domain-to-origin mapping. WebSockets work because the origin is a standard HTTPS endpoint rather than a VPC-origin endpoint. And from an IaC perspective, the system becomes straightforward to automate and reason about.&lt;/p&gt;

&lt;p&gt;Most importantly, the design uses only native AWS capabilities with no custom components or service-specific tricks, making it robust, predictable, and cloud-portable if necessary.&lt;/p&gt;

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

&lt;p&gt;Designing a multi-tenant architecture capable of handling hundreds of custom domains is not as simple as placing CloudFront in front of an ALB. Certificate limits, WebSocket support, and management complexity all influence the final design. After evaluating several approaches, we found that introducing a single internal origin domain offers the cleanest and most scalable solution. CloudFront takes responsibility for per-tenant TLS termination, while the ALB handles only a single internal certificate. The backend receives correct tenant routing through the Host header, and the system remains simple enough to maintain and automate.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>architecture</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
