<?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: Germán Neironi</title>
    <description>The latest articles on Forem by Germán Neironi (@german_neironi).</description>
    <link>https://forem.com/german_neironi</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%2F3709126%2Ff9cfde97-1127-4333-97a1-065f6c744c63.png</url>
      <title>Forem: Germán Neironi</title>
      <link>https://forem.com/german_neironi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/german_neironi"/>
    <language>en</language>
    <item>
      <title>Building in Public: The Technical Decisions Behind an AWS Cost Optimization Tool</title>
      <dc:creator>Germán Neironi</dc:creator>
      <pubDate>Fri, 27 Feb 2026 12:01:56 +0000</pubDate>
      <link>https://forem.com/german_neironi/building-in-public-the-technical-decisions-behind-an-aws-cost-optimization-tool-5bhn</link>
      <guid>https://forem.com/german_neironi/building-in-public-the-technical-decisions-behind-an-aws-cost-optimization-tool-5bhn</guid>
      <description>&lt;p&gt;I'm going to share something most founders don't: the actual technical journey of building a product from scratch.&lt;/p&gt;

&lt;p&gt;No "we raised $10M and hired 50 engineers." Just one developer and a lot of coffee.&lt;/p&gt;

&lt;p&gt;This is how I built &lt;a href="https://cloudpruneai.com" rel="noopener noreferrer"&gt;CloudPruneAI&lt;/a&gt; - an AWS cost optimization tool that scans accounts and generates infrastructure-as-code to fix waste.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem I Wanted to Solve
&lt;/h2&gt;

&lt;p&gt;After years of managing AWS infrastructure, I kept seeing the same pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Company grows fast&lt;/li&gt;
&lt;li&gt;Engineers spin up resources "temporarily"&lt;/li&gt;
&lt;li&gt;Nobody cleans them up&lt;/li&gt;
&lt;li&gt;CFO asks "why is our AWS bill so high?"&lt;/li&gt;
&lt;li&gt;Everyone panics and manually audits for a week&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The tools that existed either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost $45K+/year (CloudHealth, Cloudability)&lt;/li&gt;
&lt;li&gt;Only showed dashboards without actionable fixes&lt;/li&gt;
&lt;li&gt;Required a dedicated FinOps team to operate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted something that a solo developer or small team could use: scan, see waste, get code to fix it. Done.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack Decisions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Backend: FastAPI + Python
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why FastAPI?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Async by default (critical when you're making dozens of AWS API calls per scan)&lt;/li&gt;
&lt;li&gt;Auto-generated OpenAPI docs (saves time during frontend integration)&lt;/li&gt;
&lt;li&gt;Type hints with Pydantic (catches bugs before they reach production)&lt;/li&gt;
&lt;li&gt;Easy to deploy on Lambda with Mangum (one handler, done)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Python was the natural choice because AWS SDKs, CDK, and most infrastructure tooling lives in the Python ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend: Next.js 14 + Material UI
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why Next.js 14?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App Router is finally stable&lt;/li&gt;
&lt;li&gt;Server components reduce client bundle&lt;/li&gt;
&lt;li&gt;Easy deployment on AWS Amplify (SSR support)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Material UI gave me a professional-looking dashboard without spending weeks on design. For an MVP, speed matters more than pixel-perfect custom UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Infrastructure: AWS CDK
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why CDK over Terraform?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same language as backend (Python) — one less context switch&lt;/li&gt;
&lt;li&gt;Better AWS integration for the services I needed&lt;/li&gt;
&lt;li&gt;And honestly... I'm building a tool that generates CDK, so I should use it myself&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Database: PostgreSQL on RDS
&lt;/h3&gt;

&lt;p&gt;Simple choice. Relational data, need transactions, familiar with it. Used SQLAlchemy 2.0 with async support to keep everything non-blocking.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core: How the Scanner Works
&lt;/h2&gt;

&lt;p&gt;The scanner is the heart of the product. At a high level:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User connects their AWS account (read-only access via IAM role)&lt;/li&gt;
&lt;li&gt;The scanner runs multiple analyzers in parallel — each one specialized for a different AWS service&lt;/li&gt;
&lt;li&gt;Each analyzer calls AWS APIs, checks utilization metrics via CloudWatch, and identifies waste patterns&lt;/li&gt;
&lt;li&gt;Results are aggregated with estimated monthly savings per recommendation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key insight was making each analyzer independent and atomic. They don't know about each other. This means I can add new ones without touching existing code, and a failure in one doesn't break the others.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Differentiator: AI-Powered Code Generation
&lt;/h2&gt;

&lt;p&gt;Most cost tools stop at "you're wasting money on X." We go further: for each recommendation, you can generate a CDK project that implements the fix.&lt;/p&gt;

&lt;p&gt;I use Claude's API for code generation. The tricky part wasn't the AI — it was the infrastructure around it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generation can take 10-30 seconds&lt;/li&gt;
&lt;li&gt;API Gateway has a 30-second timeout&lt;/li&gt;
&lt;li&gt;Users don't want to stare at a spinner&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Async processing with a queue. User clicks "Generate," gets an immediate response with a task ID, and polls for completion. A separate worker processes the queue and stores results. When ready, the user downloads a ZIP with a complete CDK project.&lt;/p&gt;

&lt;p&gt;This pattern (queue + worker + polling) solved the timeout issue cleanly and scales naturally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistakes I Made
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Underestimating Auth Complexity
&lt;/h3&gt;

&lt;p&gt;I thought "just add Auth0" would take a day. It took a week.&lt;/p&gt;

&lt;p&gt;Problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Session handling between SSR and client components&lt;/li&gt;
&lt;li&gt;JWT verification on the backend&lt;/li&gt;
&lt;li&gt;Logout not actually logging out (cached sessions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lesson: Auth is never "just add a library."&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Not Setting Up Environments Early
&lt;/h3&gt;

&lt;p&gt;I built everything in staging first. When it was time for production, I had to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate all CDK stacks&lt;/li&gt;
&lt;li&gt;Create separate databases&lt;/li&gt;
&lt;li&gt;Configure separate Auth0 applications&lt;/li&gt;
&lt;li&gt;Debug environment variable issues for days&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Should have done staging + production from day one. The marginal effort is tiny compared to retrofitting later.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Overthinking the Business Model
&lt;/h3&gt;

&lt;p&gt;First idea: SaaS subscription ($99/month)&lt;br&gt;
Second idea: One-time payment per scan&lt;br&gt;
Third idea: Gainshare (percentage of savings)&lt;br&gt;
Final: Gainshare + optional subscription&lt;/p&gt;

&lt;p&gt;I spent too much time on pricing before having users. Should have just launched with something simple and iterated.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Worked Well
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Monorepo with Turborepo
&lt;/h3&gt;

&lt;p&gt;Frontend, backend, infrastructure — all in one repo. One command to run everything locally. One PR for full-stack changes. No version mismatches between services.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Early User Testing
&lt;/h3&gt;

&lt;p&gt;I scanned a friend's AWS account before the UI was even done. Found significant waste across multiple accounts.&lt;/p&gt;

&lt;p&gt;That validated the core value prop before I wrote a single line of frontend code. If the scanner hadn't found real savings, I would have known early, not after building the entire product.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Building the Hard Part First
&lt;/h3&gt;

&lt;p&gt;Scanner + code generation were the riskiest parts. I built those first.&lt;/p&gt;

&lt;p&gt;If the AI couldn't generate production-quality CDK code, the whole product wouldn't work. Better to find out early.&lt;/p&gt;

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

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

&lt;p&gt;&lt;code&gt;User → Route 53 (DNS) → splits into two paths:&lt;/code&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;AWS Amplify (Next.js SSR) → Auth0 (authentication)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;API Gateway (HTTP API) → Lambda (FastAPI) → RDS PostgreSQL + DynamoDB (cache)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Code generation flow:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lambda → SQS queue → CDK Worker Lambda → stores result → user downloads ZIP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything serverless except the database. Two isolated environments (staging + production) with separate infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Costs
&lt;/h2&gt;

&lt;p&gt;Running this in production:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RDS (db.t4g.micro)&lt;/td&gt;
&lt;td&gt;~$15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda&lt;/td&gt;
&lt;td&gt;~$5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amplify&lt;/td&gt;
&lt;td&gt;~$5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Gateway&lt;/td&gt;
&lt;td&gt;~$1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DynamoDB&lt;/td&gt;
&lt;td&gt;~$1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$27/month&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Serverless keeps costs near zero until you have real traffic. That's important when you're bootstrapping.&lt;/p&gt;

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

&lt;p&gt;Currently looking for beta testers. If you have an AWS account spending &amp;gt;$1K/month and want a free scan, &lt;a href="https://cloudpruneai.com" rel="noopener noreferrer"&gt;sign up here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In exchange, I just need 15 minutes of feedback on what works and what doesn't.&lt;/p&gt;




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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with the risky parts&lt;/strong&gt; — validate core tech before building UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set up environments early&lt;/strong&gt; — staging + production from day one&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Async processing for slow operations&lt;/strong&gt; — don't fight API timeouts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth is always harder than you think&lt;/strong&gt; — budget extra time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test with real users early&lt;/strong&gt; — even before the product is "ready"&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Questions about the stack or decisions? Drop them in the comments — happy to go deeper on any part.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>aws</category>
      <category>startup</category>
      <category>python</category>
    </item>
    <item>
      <title>I Was Writing Marketing Posts Disguised as Advice. My Audience Noticed Before I Did.</title>
      <dc:creator>Germán Neironi</dc:creator>
      <pubDate>Wed, 11 Feb 2026 18:40:29 +0000</pubDate>
      <link>https://forem.com/german_neironi/i-was-writing-marketing-posts-disguised-as-advice-my-audience-noticed-before-i-did-3236</link>
      <guid>https://forem.com/german_neironi/i-was-writing-marketing-posts-disguised-as-advice-my-audience-noticed-before-i-did-3236</guid>
      <description>&lt;p&gt;I've been building &lt;a href="https://cloudpruneai.com" rel="noopener noreferrer"&gt;CloudPruneAI&lt;/a&gt;, an AWS cost optimization tool, and part of the journey has been figuring out how to talk about it.&lt;/p&gt;

&lt;p&gt;Last night I sat down to review our LinkedIn content performance from the past month. What I found made me rethink everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data that changed my mind
&lt;/h2&gt;

&lt;p&gt;We've published about 15 LinkedIn posts since mid-January. Some did well. Some flopped. When I looked at the numbers, a clear pattern emerged:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Posts that worked:&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;Post&lt;/th&gt;
&lt;th&gt;Theme&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"The most expensive mistake I've seen in AWS? 'We'll optimize later.'"&lt;/td&gt;
&lt;td&gt;Behavioral pattern, no blame&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8,100 impressions&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloudWatch logs tip with a CLI command&lt;/td&gt;
&lt;td&gt;Practical, immediately useful&lt;/td&gt;
&lt;td&gt;Good engagement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Beta testers request&lt;/td&gt;
&lt;td&gt;Transparent, asked for help&lt;/td&gt;
&lt;td&gt;Good DMs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Posts that didn't work:&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;Post&lt;/th&gt;
&lt;th&gt;Theme&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"Most FinOps tools are just expensive dashboards"&lt;/td&gt;
&lt;td&gt;Adversarial, us vs them&lt;/td&gt;
&lt;td&gt;Low traction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Stop buying dashboards. Start deploying fixes."&lt;/td&gt;
&lt;td&gt;Direct comparison to competitors&lt;/td&gt;
&lt;td&gt;Low traction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"What if the tool that found the problem also wrote the fix?"&lt;/td&gt;
&lt;td&gt;Thinly veiled product pitch&lt;/td&gt;
&lt;td&gt;Low traction&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The difference was obvious once I saw it side by side.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I was doing wrong
&lt;/h2&gt;

&lt;p&gt;I thought I was writing helpful content. But several of my posts were really just marketing wrapped in an opinion format:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The adversarial pattern:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Other tools give you X. You actually need Y. [Implied: we give you Y]."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It seems clever when you're writing it. But readers see right through it. They scroll past because it feels like an ad, even if you never mention your product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The disguised pitch:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What if the tool that found the problem also wrote the fix?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's not a question. That's a tagline. And LinkedIn audiences can smell a tagline from three paragraphs away.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually resonated
&lt;/h2&gt;

&lt;p&gt;The post that went semi-viral (8.1K impressions for an account with ~500 connections) was this one:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The most expensive mistake I've seen in AWS? Not the m5.24xlarge someone left running. Not the 10TB of logs. It's this: 'We'll optimize later.'"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Why did it work?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It described a pattern, not a product.&lt;/strong&gt; Anyone who's worked with AWS recognized the behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It didn't point fingers.&lt;/strong&gt; No "your tools are bad" or "you're doing it wrong."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It gave something to think about.&lt;/strong&gt; The reader left with a reflection, not a sales pitch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It ended with a genuine question.&lt;/strong&gt; "What's your 'I'll fix it later' that never got fixed?" People wanted to share their own stories.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The voice we're building now
&lt;/h2&gt;

&lt;p&gt;After this analysis, we documented what we're calling our brand voice. The core principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"The engineer who's been through this and shares what they learned."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not a vendor talking to a prospect. A peer sharing a trench.&lt;/p&gt;

&lt;p&gt;Five rules we're following now:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Experience before opinion
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Before: "Most FinOps tools are just expensive dashboards."&lt;/li&gt;
&lt;li&gt;After: "A CTO told me they had 3 dashboards showing $5K in waste. Six months later, nothing changed. I asked why."&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Give before you ask
&lt;/h3&gt;

&lt;p&gt;Every post should leave the reader with something useful. If someone reads our post and doesn't need our product, they should still feel like they gained something.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Show, don't tell
&lt;/h3&gt;

&lt;p&gt;We don't say "we deliver solutions, not dashboards." We tell stories where the gap between knowing and acting cost real money. Our value proposition emerges from the narrative, not from a comparison chart.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Vulnerability over perfection
&lt;/h3&gt;

&lt;p&gt;Share mistakes, real numbers, honest doubts. Building in public means actually being public, not curating a highlight reel.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Invite conversation, not debate
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Before: "Agree or disagree?"&lt;/li&gt;
&lt;li&gt;After: "Has anyone else experienced this?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One triggers a debate. The other triggers storytelling. Storytelling builds community.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we stopped doing
&lt;/h2&gt;

&lt;p&gt;We archived several posts that were already written and scheduled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Hot take: If you're still writing CloudFormation YAML..."&lt;/strong&gt; → adversarial tone&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Stop buying dashboards. Start deploying fixes."&lt;/strong&gt; → us vs them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"What if the tool that found the problem also wrote the fix?"&lt;/strong&gt; → pitch disguised as reflection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"I ran a scan on a fintech's AWS. Found $21K/month in waste."&lt;/strong&gt; → sounds like a sales demo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Killing content you already wrote is painful. But publishing content that makes people scroll past is worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  The new content plan
&lt;/h2&gt;

&lt;p&gt;We replaced the archived posts with five new ones that follow the new voice:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"The resource nobody remembers creating"&lt;/strong&gt; - About orphaned AWS resources and the pattern of "I think someone from the previous team set that up." Practical tips for tagging and monthly cleanup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"Your staging environment doesn't sleep"&lt;/strong&gt; - Quick math on how dev/staging running 24/7 wastes 76% of its cost. Practical solution with Lambda scheduling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"Month 1: $1,974 and zero customers"&lt;/strong&gt; - Full building in public post. Real investment numbers, what we built, what we got wrong.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"The Friday ritual that saves thousands"&lt;/strong&gt; - A 10-minute weekly cost review habit anyone can start immediately. No tools required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"The conversation that changed how I think about cloud costs"&lt;/strong&gt; - A founder who knows they have waste but doesn't have bandwidth to fix it. The compound effect of "we'll get to it."&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Notice the difference: none of these posts require CloudPruneAI to exist. They're useful on their own. That's the test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm sharing this
&lt;/h2&gt;

&lt;p&gt;Because I think a lot of early-stage founders fall into the same trap.&lt;/p&gt;

&lt;p&gt;You build something you're excited about. You want to tell the world why it's different. So you write posts that explain why your approach is better than the alternatives.&lt;/p&gt;

&lt;p&gt;And it feels productive. You're "doing content marketing."&lt;/p&gt;

&lt;p&gt;But your audience doesn't care about your competitive positioning. They care about their problems. They engage with content that helps them, teaches them, or makes them feel seen.&lt;/p&gt;

&lt;p&gt;The product pitch can come later. First, earn the right to pitch by being genuinely useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real metric
&lt;/h2&gt;

&lt;p&gt;The best signal we've gotten wasn't impressions or likes. It was a DM after the "We'll optimize later" post:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This is literally what's happening at my company right now. Can we talk?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That came from a post that never mentioned CloudPruneAI. Never mentioned our product at all.&lt;/p&gt;

&lt;p&gt;That's the voice we're building toward.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm building CloudPruneAI in public — an AWS cost optimization tool that generates deployable infrastructure-as-code instead of just reports. If you're interested in following the journey, I share monthly updates with real numbers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is month 1. Total invested: $1,974.06. Paying customers: 0. Lessons learned: priceless (and free, apparently).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>marketing</category>
      <category>contentmarketing</category>
      <category>startup</category>
    </item>
    <item>
      <title>FinOps for Startups: How to Stop Bleeding Money on Cloud Without Hiring a Team</title>
      <dc:creator>Germán Neironi</dc:creator>
      <pubDate>Sun, 25 Jan 2026 14:49:41 +0000</pubDate>
      <link>https://forem.com/german_neironi/finops-for-startups-how-to-stop-bleeding-money-on-cloud-without-hiring-a-team-4i4g</link>
      <guid>https://forem.com/german_neironi/finops-for-startups-how-to-stop-bleeding-money-on-cloud-without-hiring-a-team-4i4g</guid>
      <description>&lt;p&gt;Let me share a number that should make every startup founder uncomfortable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;27% of cloud spend is wasted.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's not my opinion. That's &lt;a href="https://www.flexera.com/blog/finops/the-latest-cloud-computing-trends-flexera-2025-state-of-the-cloud-report/" rel="noopener noreferrer"&gt;Flexera's 2025 State of the Cloud Report&lt;/a&gt;. And it's actually &lt;em&gt;improved&lt;/em&gt; from previous years (it was 32% in 2022).&lt;/p&gt;

&lt;p&gt;If your startup spends $10K/month on AWS, around $2,700 is probably going to resources you don't need.&lt;/p&gt;

&lt;p&gt;The problem? Most FinOps advice assumes you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A dedicated FinOps team&lt;/li&gt;
&lt;li&gt;Enterprise tools with $45K+ annual contracts&lt;/li&gt;
&lt;li&gt;Time to build dashboards and review reports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Startups have none of that. You have a Slack channel where someone occasionally posts "why is our AWS bill so high?" and everyone shrugs.&lt;/p&gt;

&lt;p&gt;Let me show you how to do FinOps without the overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is FinOps (In Startup Terms)
&lt;/h2&gt;

&lt;p&gt;FinOps is just "don't waste money on cloud." That's it.&lt;/p&gt;

&lt;p&gt;The fancy definition involves "cloud financial management" and "cross-functional collaboration." But for a 10-person startup, it means:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Know what you're spending&lt;/li&gt;
&lt;li&gt;Understand why&lt;/li&gt;
&lt;li&gt;Fix the obvious waste&lt;/li&gt;
&lt;li&gt;Don't let it creep back&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No team required. No enterprise tools. Just discipline.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 80/20 of Cloud Waste
&lt;/h2&gt;

&lt;p&gt;After analyzing dozens of AWS accounts, I've found that 80% of waste comes from 5 sources:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Zombie Resources (30% of waste)
&lt;/h3&gt;

&lt;p&gt;Resources that were created and forgotten:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 instances from that "quick test" 6 months ago&lt;/li&gt;
&lt;li&gt;Load balancers pointing to nothing&lt;/li&gt;
&lt;li&gt;EBS volumes from terminated instances&lt;/li&gt;
&lt;li&gt;Unattached Elastic IPs ($3.60/month each - sounds small until you have 20)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quick fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find unattached EBS volumes&lt;/span&gt;
aws ec2 describe-volumes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;status,Values&lt;span class="o"&gt;=&lt;/span&gt;available &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Volumes[*].[VolumeId,Size,CreateTime]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Oversized Instances (25% of waste)
&lt;/h3&gt;

&lt;p&gt;That m5.xlarge "because we might need it" running at 8% CPU.&lt;/p&gt;

&lt;p&gt;This is the most common waste in startups. Someone provisions a big instance "to be safe," and no one ever checks if it's actually needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check CPU utilization (last 7 days)&lt;/span&gt;
aws cloudwatch get-metric-statistics &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; AWS/EC2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metric-name&lt;/span&gt; CPUUtilization &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dimensions&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;InstanceId,Value&lt;span class="o"&gt;=&lt;/span&gt;i-YOUR_INSTANCE_ID &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--start-time&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'7 days ago'&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; +%Y-%m-%dT%H:%M:%SZ&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-time&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; +%Y-%m-%dT%H:%M:%SZ&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--period&lt;/span&gt; 3600 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--statistics&lt;/span&gt; Average
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If average CPU is under 20%, you're probably oversized.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Logs Growing Forever (20% of waste)
&lt;/h3&gt;

&lt;p&gt;CloudWatch Logs have &lt;strong&gt;no default retention&lt;/strong&gt;. Your logs from 2022 are still there, and you're still paying for them.&lt;/p&gt;

&lt;p&gt;I've heard of companies paying $40K+/month just for log storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find log groups without retention&lt;/span&gt;
aws logs describe-log-groups &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'logGroups[?retentionInDays==`null`].[logGroupName,storedBytes]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set retention to 14 or 30 days for most logs. You probably don't need 3-year-old debug logs.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Wrong Storage Classes (15% of waste)
&lt;/h3&gt;

&lt;p&gt;Data that's accessed once a year sitting in S3 Standard instead of Glacier.&lt;/p&gt;

&lt;p&gt;Or worse: gp2 EBS volumes instead of gp3 (gp3 is 20% cheaper with better performance).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find gp2 volumes (should be gp3)&lt;/span&gt;
aws ec2 describe-volumes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;volume-type,Values&lt;span class="o"&gt;=&lt;/span&gt;gp2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Volumes[*].[VolumeId,Size,VolumeType]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Idle RDS Instances (10% of waste)
&lt;/h3&gt;

&lt;p&gt;Development databases running 24/7 when they're only used during work hours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick fix:&lt;/strong&gt; Aurora Serverless v2 for dev/staging, or at minimum, stop instances outside work hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 15-Minute Weekly Audit
&lt;/h2&gt;

&lt;p&gt;You don't need a FinOps platform. You need 15 minutes every Monday.&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 1: Check the Bill
&lt;/h3&gt;

&lt;p&gt;Go to AWS Cost Explorer. Look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Top 5 services by cost&lt;/li&gt;
&lt;li&gt;Any spikes vs last month&lt;/li&gt;
&lt;li&gt;Cost by tag (if you're tagging... you are tagging, right?)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Week 2: Hunt Zombies
&lt;/h3&gt;

&lt;p&gt;Run the commands above. Delete what you don't need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 3: Check Utilization
&lt;/h3&gt;

&lt;p&gt;Look at your biggest EC2 instances and RDS databases. Are they actually busy?&lt;/p&gt;

&lt;h3&gt;
  
  
  Week 4: Review Reservations
&lt;/h3&gt;

&lt;p&gt;Are you running anything consistently 24/7 for 6+ months? Consider Reserved Instances or Savings Plans.&lt;/p&gt;

&lt;p&gt;Rotate through these. Takes 15 minutes if you're focused.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automation That Actually Helps
&lt;/h2&gt;

&lt;p&gt;Some things should be automated from day one:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Budget Alerts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws budgets create-budget &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--account-id&lt;/span&gt; YOUR_ACCOUNT_ID &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--budget&lt;/span&gt; &lt;span class="s1"&gt;'{
    "BudgetName": "Monthly-Limit",
    "BudgetLimit": {"Amount": "1000", "Unit": "USD"},
    "TimeUnit": "MONTHLY",
    "BudgetType": "COST"
  }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--notifications-with-subscribers&lt;/span&gt; &lt;span class="s1"&gt;'[{
    "Notification": {
      "NotificationType": "ACTUAL",
      "ComparisonOperator": "GREATER_THAN",
      "Threshold": 80
    },
    "Subscribers": [{
      "SubscriptionType": "EMAIL",
      "Address": "your@email.com"
    }]
  }]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get alerted at 80% of budget. Not at 150%.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Auto-Stop Dev Environments
&lt;/h3&gt;

&lt;p&gt;Use AWS Instance Scheduler or a simple Lambda:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ec2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ec2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Stop instances tagged with AutoStop=true
&lt;/span&gt;    &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe_instances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;Filters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tag:AutoStop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Values&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;instance-state-name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Values&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;running&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;reservation&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Reservations&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reservation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Instances&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;ec2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop_instances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InstanceIds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;InstanceId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it at 8pm, start instances at 8am. Save 50%+ on dev instances.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Lifecycle Policies
&lt;/h3&gt;

&lt;p&gt;Always set these on S3 buckets:&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;"Rules"&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;"ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TransitionToIA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Enabled"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Transitions"&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;"Days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"StorageClass"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"STANDARD_IA"&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;"Expiration"&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;"Days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;365&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data older than 30 days moves to cheaper storage. Data older than a year gets deleted.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use Tools
&lt;/h2&gt;

&lt;p&gt;DIY works until ~$20K/month. After that, the time spent manually auditing exceeds the cost of tools.&lt;/p&gt;

&lt;p&gt;But here's my advice: &lt;strong&gt;don't buy dashboards, buy action&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Most FinOps tools tell you what's wrong. Few tell you how to fix it. Even fewer give you the actual code to implement fixes.&lt;/p&gt;

&lt;p&gt;That's why we built &lt;a href="https://cloudpruneai.com" rel="noopener noreferrer"&gt;CloudPruneAI&lt;/a&gt; - scan your AWS, get deployable CDK code, not a 50-page PDF.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mindset Shift
&lt;/h2&gt;

&lt;p&gt;FinOps isn't a one-time cleanup. It's a habit.&lt;/p&gt;

&lt;p&gt;Every time you create a resource, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does this need to run 24/7?&lt;/li&gt;
&lt;li&gt;What's the right size?&lt;/li&gt;
&lt;li&gt;When should this be deleted?&lt;/li&gt;
&lt;li&gt;Is it tagged so we know who owns it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Build this into your engineering culture, and you'll never need a dedicated FinOps team.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;27% of cloud spend is waste&lt;/strong&gt; - yours is probably similar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;80% of waste is 5 things&lt;/strong&gt;: zombies, oversizing, logs, storage class, idle DBs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;15 minutes/week&lt;/strong&gt; is enough for most startups&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate the basics&lt;/strong&gt;: budgets, auto-stop, lifecycle policies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools should give you action&lt;/strong&gt;, not just dashboards&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Quick Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Quick Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Unattached EBS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws ec2 describe-volumes --filters Name=status,Values=available&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unattached EIPs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws ec2 describe-addresses --query 'Addresses[?AssociationId==null]'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No log retention&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws logs describe-log-groups --query 'logGroups[?retentionInDays==null]'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gp2 volumes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws ec2 describe-volumes --filters Name=volume-type,Values=gp2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stopped instances&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws ec2 describe-instances --filters Name=instance-state-name,Values=stopped&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;em&gt;What's your biggest cloud cost pain point? Let me know in the comments - I might cover it in a future post.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>finops</category>
      <category>startup</category>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Deploying Real Infrastructure Easily (AWS CDK)</title>
      <dc:creator>Germán Neironi</dc:creator>
      <pubDate>Fri, 16 Jan 2026 18:47:20 +0000</pubDate>
      <link>https://forem.com/german_neironi/deploying-real-infrastructure-easily-aws-cdk-4npd</link>
      <guid>https://forem.com/german_neironi/deploying-real-infrastructure-easily-aws-cdk-4npd</guid>
      <description>&lt;p&gt;You've probably heard about Infrastructure as Code. Maybe you've even written some CloudFormation YAML and felt your soul leave your body around line 847.&lt;/p&gt;

&lt;p&gt;There's a better way.&lt;/p&gt;

&lt;p&gt;AWS CDK (Cloud Development Kit) lets you define infrastructure using real programming languages - TypeScript, Python, Java, Go. No more YAML indentation nightmares. No more copy-pasting 200-line templates you found on Stack Overflow.&lt;/p&gt;

&lt;p&gt;Let me show you how to go from zero to deploying real infrastructure in 10 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AWS CDK?
&lt;/h2&gt;

&lt;p&gt;CDK is a framework that lets you define AWS resources using code. You write TypeScript (or Python, etc.), CDK converts it to CloudFormation, and deploys it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Code (TypeScript) → CDK → CloudFormation → AWS Resources
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The magic: you get loops, conditionals, functions, type checking, and IDE autocomplete. Things that are painful or impossible in YAML.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup (2 minutes)
&lt;/h2&gt;

&lt;p&gt;You need Node.js and AWS CLI configured. Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; aws-cdk
&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-first-cdk &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;my-first-cdk
cdk init app &lt;span class="nt"&gt;--language&lt;/span&gt; typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-first-cdk/
├── bin/
│   └── my-first-cdk.ts    # Entry point
├── lib/
│   └── my-first-cdk-stack.ts  # Your infrastructure
├── package.json
└── cdk.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Your First Stack (3 minutes)
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;lib/my-first-cdk-stack.ts&lt;/code&gt;. Let's create an S3 bucket with some sensible defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-s3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;constructs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFirstCdkStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StackProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create an S3 bucket&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyBucket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;versioned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;encryption&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BucketEncryption&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;S3_MANAGED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;blockPublicAccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BlockPublicAccess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BLOCK_ALL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;removalPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RemovalPolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DESTROY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// For dev only!&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Output the bucket name&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CfnOutput&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BucketName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucketName&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;p&gt;That's it. A secure, versioned S3 bucket in 15 lines of readable code.&lt;/p&gt;

&lt;p&gt;The equivalent CloudFormation? Around 40 lines of YAML.&lt;/p&gt;

&lt;h2&gt;
  
  
  See What You're Deploying (1 minute)
&lt;/h2&gt;

&lt;p&gt;Before deploying, you can see exactly what CloudFormation CDK will generate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cdk synth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And see the diff against your current AWS state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cdk diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows you exactly what will be created, modified, or deleted. No surprises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy (2 minutes)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cdk bootstrap  &lt;span class="c"&gt;# First time only, sets up CDK in your account&lt;/span&gt;
cdk deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch your terminal. CDK creates a CloudFormation stack, provisions the resources, and shows you the outputs.&lt;/p&gt;

&lt;p&gt;Done. You have a production-ready S3 bucket.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why CDK Beats YAML
&lt;/h2&gt;

&lt;p&gt;Let me show you the real power. Say you need 3 buckets for different environments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;environments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;staging&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;environments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&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="s2"&gt;`DataBucket-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bucketName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`myapp-data-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;versioned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Only version prod&lt;/span&gt;
    &lt;span class="na"&gt;lifecycleRules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
      &lt;span class="na"&gt;expiration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;days&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// Auto-cleanup non-prod&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;p&gt;Try doing that cleanly in YAML. I'll wait.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Pattern: Lambda + API Gateway
&lt;/h2&gt;

&lt;p&gt;Here's something more practical - a serverless API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-lambda&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;apigw&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-apigateway&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create Lambda function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Function&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ApiHandler&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODEJS_18_X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lambda&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.handler&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;memorySize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&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 API Gateway&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;apigw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RestApi&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;restApiName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;My Service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Connect them&lt;/span&gt;
&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;apigw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LambdaIntegration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lambda function + API Gateway + all the IAM permissions, wired up correctly. In 20 lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Optimization Patterns
&lt;/h2&gt;

&lt;p&gt;One thing I've learned building &lt;a href="https://cloudpruneai.com" rel="noopener noreferrer"&gt;CloudPruneAI&lt;/a&gt;: most cloud waste comes from missing simple configurations. CDK makes it easy to enforce good defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Always set log retention (CloudWatch logs grow forever by default!)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;logs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-logs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Function&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyFunction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... config&lt;/span&gt;
  &lt;span class="na"&gt;logRetention&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RetentionDays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TWO_WEEKS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Don't pay for logs forever&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Always use lifecycle rules on S3&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bucket&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LogsBucket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;lifecycleRules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="na"&gt;transitions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
      &lt;span class="na"&gt;storageClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StorageClass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INTELLIGENT_TIERING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;transitionAfter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;days&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;expiration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;days&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;365&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;These patterns prevent the "silent cost creep" that hits most AWS accounts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Destroying Resources
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cdk destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CDK removes everything it created. Clean.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;1. Bootstrap once per account/region&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cdk bootstrap aws://ACCOUNT_ID/REGION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Stateful resources need care&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default, CDK protects databases and buckets from accidental deletion. For dev environments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;removalPolicy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RemovalPolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DESTROY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;autoDeleteObjects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// For S3 buckets&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Use cdk diff before deploy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Always. It's saved me from many "oops" moments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read constructs&lt;/strong&gt;: Browse &lt;a href="https://constructs.dev/" rel="noopener noreferrer"&gt;Construct Hub&lt;/a&gt; for pre-built patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try L2 constructs&lt;/strong&gt;: Higher-level abstractions like &lt;code&gt;ApplicationLoadBalancedFargateService&lt;/code&gt; that wire up 10+ resources in one line&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organize with stages&lt;/strong&gt;: Use &lt;code&gt;cdk.Stage&lt;/code&gt; for multi-environment deployments&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cdk/v2/guide/home.html" rel="noopener noreferrer"&gt;AWS CDK Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cdkpatterns.com/" rel="noopener noreferrer"&gt;CDK Patterns&lt;/a&gt; - Real-world examples&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://constructs.dev/" rel="noopener noreferrer"&gt;Construct Hub&lt;/a&gt; - Community constructs&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;CDK changed how I think about infrastructure. It's not a config file you maintain - it's code you can test, refactor, and actually understand 6 months later.&lt;/p&gt;

&lt;p&gt;Give it 10 minutes. Your future self will thank you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's your experience with IaC? Still using CloudFormation YAML, or have you moved to CDK/Terraform? Drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cdk</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>5 AWS Resources You're Probably Overpaying For (And How to Fix Each One)</title>
      <dc:creator>Germán Neironi</dc:creator>
      <pubDate>Tue, 13 Jan 2026 13:53:53 +0000</pubDate>
      <link>https://forem.com/german_neironi/5-aws-resources-youre-probably-overpaying-for-and-how-to-fix-each-one-4p0o</link>
      <guid>https://forem.com/german_neironi/5-aws-resources-youre-probably-overpaying-for-and-how-to-fix-each-one-4p0o</guid>
      <description>&lt;p&gt;Last month I analyzed 249 EC2 instances across 3 AWS accounts for a mid-market fintech company. The result? &lt;strong&gt;$256,000/year in potential savings&lt;/strong&gt;. That's $21,000 every month going to waste.&lt;/p&gt;

&lt;p&gt;The scary part: this isn't unusual. According to Flexera's 2024 State of the Cloud Report, &lt;strong&gt;32% of cloud spend is wasted&lt;/strong&gt;. Most companies have no idea they're overpaying.&lt;/p&gt;

&lt;p&gt;Here are the 5 most common culprits I find in almost every AWS account—and how to fix them.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Oversized EC2 Instances
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; You launched a &lt;code&gt;t3.xlarge&lt;/code&gt; because you weren't sure what you'd need. Now it's been running at 5% CPU for 6 months.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How common:&lt;/strong&gt; In my analysis, &lt;strong&gt;70-80% of instances&lt;/strong&gt; were oversized by at least one size class.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to detect:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check average CPU over last 14 days&lt;/span&gt;
aws cloudwatch get-metric-statistics &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; AWS/EC2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metric-name&lt;/span&gt; CPUUtilization &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dimensions&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;InstanceId,Value&lt;span class="o"&gt;=&lt;/span&gt;i-xxxxx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--start-time&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'14 days ago'&lt;/span&gt; +%Y-%m-%dT%H:%M:%S&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-time&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%Y-%m-%dT%H:%M:%S&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--period&lt;/span&gt; 86400 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--statistics&lt;/span&gt; Average
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; If average CPU is below 20% for 2+ weeks, downsize. A &lt;code&gt;t3.medium&lt;/code&gt; at $30/month vs &lt;code&gt;t3.xlarge&lt;/code&gt; at $120/month adds up fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Potential savings:&lt;/strong&gt; 50-75% per instance&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Unattached EBS Volumes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; You terminated an instance but forgot to delete its volumes. Now you're paying for storage nobody uses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How common:&lt;/strong&gt; I typically find 5-15 orphan volumes per account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to detect:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-volumes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;status,Values&lt;span class="o"&gt;=&lt;/span&gt;available &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Volumes[*].[VolumeId,Size,CreateTime]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a volume shows &lt;code&gt;status: available&lt;/code&gt;, it's not attached to anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Delete them. But first, create a snapshot if you're paranoid (snapshots are ~$0.05/GB/month vs $0.10/GB/month for volumes).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Potential savings:&lt;/strong&gt; $0.10/GB/month per volume&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Old EBS Snapshots
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; Automated backups create snapshots daily. Nobody deletes them. A year later you have 365 snapshots of the same volume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to detect:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-snapshots &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--owner-ids&lt;/span&gt; self &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Snapshots[?StartTime&amp;lt;=`2024-01-01`].[SnapshotId,VolumeSize,StartTime]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Keep the last 7-30 days (depending on your compliance needs)&lt;/li&gt;
&lt;li&gt;Delete everything older&lt;/li&gt;
&lt;li&gt;Set up a lifecycle policy with AWS Data Lifecycle Manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Potential savings:&lt;/strong&gt; Can be thousands/month for active accounts&lt;/p&gt;




&lt;h2&gt;
  
  
  4. EBS gp2 Volumes (Instead of gp3)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; gp3 launched in 2020 with 20% lower base cost AND better performance. Yet most accounts still have gp2 volumes because "it works, why change it?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How common:&lt;/strong&gt; In my analysis, 60%+ of volumes were still gp2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to detect:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-volumes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Volumes[?VolumeType==`gp2`].[VolumeId,Size,VolumeType]'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Migrate to gp3. It's a live operation, no downtime required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 modify-volume &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--volume-id&lt;/span&gt; vol-xxxxx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--volume-type&lt;/span&gt; gp3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Potential savings:&lt;/strong&gt; 20% per volume, zero effort&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Idle RDS Instances
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; A dev database someone created for testing 8 months ago. A staging DB that nobody uses anymore. They're running 24/7.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How common:&lt;/strong&gt; 1-3 per account, often in non-prod environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to detect:&lt;/strong&gt; Check connections over the last 14 days:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudwatch get-metric-statistics &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; AWS/RDS &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metric-name&lt;/span&gt; DatabaseConnections &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dimensions&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;DBInstanceIdentifier,Value&lt;span class="o"&gt;=&lt;/span&gt;my-db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--start-time&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'14 days ago'&lt;/span&gt; +%Y-%m-%dT%H:%M:%S&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-time&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%Y-%m-%dT%H:%M:%S&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--period&lt;/span&gt; 86400 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--statistics&lt;/span&gt; Maximum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If max connections = 0 for 2 weeks, it's idle.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;For dev/test: Stop it (you can start it when needed)&lt;/li&gt;
&lt;li&gt;For truly unused: Take a final snapshot and delete it&lt;/li&gt;
&lt;li&gt;Consider Aurora Serverless for dev workloads (scales to zero)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Potential savings:&lt;/strong&gt; $50-500/month per idle instance&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Example: Mid-Market Fintech
&lt;/h2&gt;

&lt;p&gt;Here's a real analysis I ran recently for a fintech company with 3 AWS accounts:&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;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EC2 instances analyzed&lt;/td&gt;
&lt;td&gt;249&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recommendations generated&lt;/td&gt;
&lt;td&gt;72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monthly savings potential&lt;/td&gt;
&lt;td&gt;$21,340&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Annual savings potential&lt;/td&gt;
&lt;td&gt;$256,076&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Oversized instances&lt;/strong&gt;: 60%+ were running at &amp;lt;20% average CPU&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;gp2 → gp3 migrations&lt;/strong&gt;: Immediate 20% savings, zero downtime required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orphan resources&lt;/strong&gt;: Multiple unattached volumes and outdated snapshots&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This aligns with industry benchmarks—Flexera reports 32% of cloud spend is typically wasted, and Gartner finds 2-3x overprovisioning is common.&lt;/p&gt;




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

&lt;p&gt;Running these checks manually is tedious. And even if you do it once, waste accumulates again within weeks.&lt;/p&gt;

&lt;p&gt;That's why I built &lt;a href="https://cloudpruneai.com" rel="noopener noreferrer"&gt;CloudPruneAI&lt;/a&gt;—it scans your AWS accounts automatically and generates Infrastructure as Code (CDK) to implement the fixes. Instead of a report you'll forget about, you get deployable code.&lt;/p&gt;

&lt;p&gt;But even if you never use a tool, run these 5 checks today. You might be surprised what you find.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What's the biggest AWS cost surprise you've discovered?&lt;/strong&gt; I'd love to hear your stories in the comments.&lt;/p&gt;

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