惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
量子位
The Cloudflare Blog
美团技术团队
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
Spread Privacy
Spread Privacy
P
Proofpoint News Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 三生石上(FineUI控件)
T
Tor Project blog
博客园 - 司徒正美
宝玉的分享
宝玉的分享
T
Threatpost
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Secure Thoughts
T
Threat Research - Cisco Blogs
Hacker News: Ask HN
Hacker News: Ask HN
Jina AI
Jina AI
博客园 - 聂微东
A
Arctic Wolf
I
Intezer
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
爱范儿
爱范儿
Hugging Face - Blog
Hugging Face - Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
小众软件
小众软件
T
Tailwind CSS Blog
The Hacker News
The Hacker News
L
LINUX DO - 最新话题
Hacker News - Newest:
Hacker News - Newest: "LLM"
WordPress大学
WordPress大学
S
SegmentFault 最新的问题
TaoSecurity Blog
TaoSecurity Blog
Project Zero
Project Zero
博客园 - 叶小钗
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Cloudbric
Cloudbric
雷峰网
雷峰网
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
大猫的无限游戏
大猫的无限游戏
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Troy Hunt's Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
V2EX - 技术
V2EX - 技术
The GitHub Blog
The GitHub Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
FinOps Hands-On: AWS Costs + CO e in Every PR with Infracost & Terraform
Jessica Apar · 2026-05-02 · via DEV Community

Have you ever felt that knot in your stomach when running terraform apply, unsure of how many zeros will show up on your AWS bill at the end of the month? As a Cloud professional transitioning into DevOps, my goal isn't just to build infrastructure that works, but infrastructure that is sustainable and governed.

In this article, I'll walk you through a hands-on project where I integrated Infracost directly into my CI/CD pipeline. The goal is simple yet powerful: every time I propose a change via Pull Request, the system automatically calculates the financial impact and posts a detailed comment. This is FinOps in action!


What is Infracost?

For those unfamiliar, Infracost anticipates cloud costs and integrates them into your engineering workflow. It provides cost estimates for Terraform, CloudFormation, and AWS CDK before deployment, identifying FinOps issues aligned with well-architected frameworks—fixable with a single merge.

Fully compatible with AWS, Azure, and Google Cloud, it's essential for multicloud setups. Dive deeper in the official Infracost docs.


Alignment with AWS Well-Architected Framework

My cloud journey taught me that building on AWS goes beyond deploying resources—it's about excellence standards. This project is rooted in the AWS Well-Architected Framework, focusing on two vital pillars:

Cost Optimization: Shift visibility from month-end to code time, spotting oversized resources pre-creation for efficient investment.

Sustainability (GreenOps): Use Infracost to estimate $CO_2e$ emissions, enabling eco-friendly architectural choices.


Project Architecture

To make it easier to understand how everything connects, I’ve prepared this diagram illustrating our automation flow:

As you can see in the diagram, the flow is divided into two fundamental parts:

The CI/CD Pipeline

Pull Request: Upon pushing the code to GitHub, a GitHub Actions workflow is triggered.

Analysis: The pipeline executes a terraform plan and Infracost analyzes this plan, generating the cost table directly as a PR comment.


Project Structure: Organizing Folders and Files

Organization is the foundation of any Infrastructure as Code (IaC) project. A well-defined structure simplifies automation and ensures that the infrastructure is scalable and easy for other developers to understand. To make this lab simple to replicate, the project is built on a modular structure.

Modularization is more than just organization; it is a best practice that allows different layers — such as Network, Security, and Application — to be managed independently, ensuring a proper separation of concerns.

infracost_aws/
├── .github/
│   └── workflows/
│       └── infracost.yml      # Pipeline automation
├── modules/
│   ├── network/               # Network layer (VPC, Subnets)
│   └── compute/               # Cost-generating resources (EC2, RDS, S3)
├── main.tf                    # Module orchestrator
├── providers.tf               # Identity and Governance
├── terraform.tfvars           # Variable values
└── variables.tf               # Global definitions

Enter fullscreen mode Exit fullscreen mode


The Cloud Contract: providers.tf

Every Terraform project begins with the providers file. This is where we establish the connection with the cloud provider and set the governance strategy right from "day zero."

Here is the configuration I used for this project:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"

  # The FinOps and Governance pillar starts here!
  default_tags {
    tags = {
      Project     = "FinOps-Infracost-Study"
      ManagedBy   = "Terraform"
      Environment = "Dev"
      Service     = "FinOps-Project"
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

Why is this configuration strategic?

Provider Versioning: Locking the version (e.g., ~> 5.0) prevents automatic provider updates from breaking the code, ensuring pipeline stability.

The Magic of default_tags: This is the most efficient way to implement cost traceability. By declaring tags in the provider block, all compatible resources (EC2, RDS, S3, etc.) automatically inherit these labels.

Hands-on FinOps: With Environment and Service tags, finance teams can filter invoices with surgical precision, eliminating "orphan" resources and simplifying audits.


Variables: The Power of Parameterization

In Infrastructure as Code, variables act like function arguments. They allow us to write generic code that can be adapted to different environments (Dev, Stage, Prod) without rewriting the core logic. To keep the project organized and simple to replicate, I split this logic into two distinct files:

  1. variables.tf: The "Contract" In this file, I define which variables my project accepts, their types (string, number, list), and an optional description. It’s the "blueprint" telling Terraform what to expect.
variable "aws_region" {
  description = "AWS region where resources will be created"
  type        = string
}

variable "instance_type" {
  description = "EC2 instance type"
  type        = string
}

variable "db_instance_class" {
  description = "RDS database instance class"
  type        = string
}

Enter fullscreen mode Exit fullscreen mode

  1. terraform.tfvars: The "Control Panel" This is where the FinOps magic happens. Instead of searching through lines of code for instance sizes, I centralize all values here.
aws_region        = "us-east-1"
instance_type     = "c6g.2xlarge"
db_instance_class = "db.t4g.medium"

Enter fullscreen mode Exit fullscreen mode

Why separate definitions from values?

Adhering to Cloud excellence standards makes this separation essential. It provides three fundamental benefits:

FinOps Agility: If Infracost warns me that costs are too high, I don't need to hunt for instance types across multiple .tf files. I change only the terraform.tfvars, push the update, and see the new cost calculation instantly.

Security and Reusability: The core code (modules) remains immutable. This prevents accidental architecture errors while only adjusting "parts" (values). It also helps avoid hardcoding sensitive data.

Standardization: For those replicating this lab, having a single configuration file makes learning much more intuitive. You focus on the parameters that truly impact infrastructure and costs.


The Orchestrator: main.tf (Root)

The main.tf file at the root of the project acts as the conductor of an orchestra. It doesn’t create resources directly; instead, it calls the modules we’ve defined and passes the necessary information between them.

In this project, modularization is a strategic choice. I separate the Network (base infrastructure) from the Compute (where costs are more volatile). Here is how the module calls look:

# Network Module: Creates VPC, Subnets, and Gateways
module "network" {
  source     = "./modules/network"
  aws_region = var.aws_region
}

# Compute Module: Creates EC2, RDS, and S3
module "compute" {
  source            = "./modules/compute"
  vpc_id            = module.network.vpc_id
  public_subnet_id  = module.network.public_subnet_id
  private_subnet_id = module.network.private_subnet_id

  # Passing the cost-related variables defined in terraform.tfvars
  instance_type     = var.instance_type
  db_instance_class = var.db_instance_class
}

Enter fullscreen mode Exit fullscreen mode

Why Module Integration Matters

The key takeaway here is interdependency. Notice that the compute module receives the vpc_id and subnets directly from the network module outputs.

Security by Design: By passing the private_subnet_id to the RDS database, I ensure it is never exposed to the public internet.

Flexibility: If I need to overhaul the network architecture, my compute module remains untouched as long as the network outputs remain consistent.


The Resource Layer: modules/compute/recursos.tf

Now that we understand how the orchestrator organizes the execution, let's dive into the layer where the "magic" (and the cost) actually happens: the Compute module.

In this file, I have configured three fundamental AWS services: EC2, RDS, and S3. The key point here is not just creating the resource, but how the variables we defined earlier in terraform.tfvars are applied to control costs.

# EC2 Instance for the Web Server
resource "aws_instance" "web_server" {
  ami           = "ami-0c101f26f147fa7fd" # Amazon Linux 2023
  instance_type = var.instance_type
  subnet_id     = var.public_subnet_id

  tags = {
    Name = "WebServer-FinOps"
  }
}

# RDS Database (PostgreSQL)
resource "aws_db_instance" "database" {
  allocated_storage      = 20
  db_name                = "finopsdb"
  engine                 = "postgres"
  engine_version         = "16.1"
  instance_class         = var.db_instance_class
  username               = "admin"
  password               = "password123" # In prod, use Secrets Manager!
  parameter_group_name   = "default.postgres16"
  skip_final_snapshot    = true
  db_subnet_group_name   = aws_db_subnet_group.default.name
  vpc_security_group_ids = [aws_security_group.db_sg.id]
  storage_type           = "gp3" # Strategic FinOps decision
}

# S3 Bucket for Static Assets
resource "aws_s3_bucket" "assets" {
  bucket = "finops-project-assets-jessica"
}

Enter fullscreen mode Exit fullscreen mode

Strategic Decisions in the Code:

  1. Instance Flexibility: Notice that both EC2 and RDS use variables for their classes/types. This allows me to switch from an expensive family (like C5) to a more efficient one (like Graviton/C6g) by simply changing a text file.

  2. Smart Storage (gp2 vs gp3): In the RDS resource, I set the storage_type to gp3. This is a classic FinOps recommendation, as gp3 is typically 20% cheaper than gp2 while providing better, independent performance.

  3. Security and Isolation: The database is linked to private subnets, ensuring that the cost of security (preventing breaches) is mitigated by proper network design from the start.


Visualizing Results: outputs.tf

After Terraform orchestrates our entire AWS infrastructure, we need a way to retrieve essential data for our daily operations. Outputs act as the "receipt" of the operation.

output "web_server_public_ip" {
  description = "Public IP address of the EC2 instance"
  value       = module.compute.web_server_public_ip
}

output "rds_endpoint" {
  description = "Connection endpoint for the RDS database"
  value       = module.compute.rds_endpoint
}

Enter fullscreen mode Exit fullscreen mode


Inside the Modules: Network and Compute

To ensure our architecture is scalable, each folder within modules/ contains its own set of files. This allows me to test the network module in isolation before even considering the servers.

  1. Network Module (modules/network/) This is the foundation. Without a configured VPC and subnets, we have nowhere to "park" our instances.

variables.tf: This is where I define parameters like the VPC CIDR block.

main.tf: Contains the logic to create the VPC, Internet Gateway, and Subnets (public and private).

outputs.tf: This is the crucial part. I need to "export" the VPC ID and Subnet IDs so the compute module can use them.

# modules/network/outputs.tf
output "vpc_id" {
  value = aws_vpc.main.id
}

output "public_subnet_id" {
  value = aws_subnet.public.id
}

output "private_subnet_id" {
  value = aws_subnet.private.id
}

Enter fullscreen mode Exit fullscreen mode

  1. Compute Module (modules/compute/)
    This is where Infracost focuses most of its analysis, as it houses the resources that generate direct hourly usage charges.

  2. variables.tf: It receives the IDs coming from the network module and the instance classes defined in the root terraform.tfvars.

  3. recursos.tf: (Which we have already detailed) where we create the EC2, RDS, and S3.

  4. outputs.tf: Returns information such as the server's public IP so I can access it.

Just as the network module exports IDs so we can build our resources, the compute module must return essential information for us to interact with the infrastructure after provisioning.

Since this project focuses on FinOps and governance, having well-defined outputs helps with quick auditing of what has been created.

# modules/compute/outputs.tf

output "web_server_public_ip" {
  description = "Public IP address for SSH or HTTP access"
  value       = aws_instance.web_server.public_ip
}

output "rds_endpoint" {
  description = "Connection endpoint for the database"
  value       = aws_db_instance.database.endpoint
}

Enter fullscreen mode Exit fullscreen mode

Why does this matter?

  1. Connectivity: Without the public IP or the database endpoint, the infrastructure exists in AWS but remains inaccessible.

  2. Transparency: In GitHub Actions, these values can be displayed at the end of the pipeline, confirming that the resources mapped by Infracost were indeed created as planned.


Technical Breakdown: GitHub Actions & Security

Workload Identity Federation (OIDC)

Security is non-negotiable. By using OIDC, we eliminate the need for persistent AWS Access Keys. The id-token: write permission allows GitHub Actions to request short-lived, temporary tokens directly from AWS, ensuring a "Keyless" and highly secure authentication flow.

In our code, this is enabled by this block:

permissions:
  id-token: write   # Obrigatório para solicitar o token JWT da AWS
  contents: read    # Para ler o código do repositório
  pull-requests: write # Para o Infracost comentar no PR

Enter fullscreen mode Exit fullscreen mode

Setting Up the "Bridge" in AWS (Console)

Step 1: Create the Identity Provider (OIDC)

  1. Go to the IAM service in the AWS Console.
  2. In the left sidebar, click Identity Providers.
  3. Click Add provider.
  4. Select OpenID Connect.
  5. For Provider URL, paste: [https://token.actions.githubusercontent.com](https://token.actions.githubusercontent.com) and click Get thumbprint.
  6. For Audience, type: sts.amazonaws.com.
  7. Click Add provider.

Step 2: Create the IAM Role for GitHub Actions

  1. In the IAM sidebar, click Roles and then Create role.
  2. Select Web Identity.
  3. Under Identity provider, select the one you just created.
  4. Under Audience, select sts.amazonaws.com.
  5. Click Next, add the necessary permissions (e.g., specific Terraform policies), and click Next.
  6. Name the role (e.g., GitHubActionsInfracostRole) and create it.

Step 3: Refine the Trust Policy

To ensure only your repository can assume this role, edit the Trust Relationship:

  1. Open your new Role, go to the Trust relationships tab, and click Edit trust policy.
  2. Ensure the sub condition points strictly to your GitHub repository as shown in the JSON block above.

Workflow Jobs Breakdown

  1. Baseline Main: Captures the current infrastructure cost from the main branch.

  2. Diff Analysis: Compares your new Pull Request code against the baseline to calculate the exact financial impact.

  3. Post Results: Delivers a visual cost breakdown directly into the PR. The continue-on-error: true setting ensures that minor commenting issues don't block critical deployments.


Why Developer Feedback Matters?

Bringing cost visibility into the PR phase allows for immediate course correction. It empowers developers to align architectural choices with Cost Optimization and Sustainability ($CO_2e$) before a single cent is spent.


Impact on Pull Request (PR)

Strategic Insight: Notice that by switching from a t3.micro instance to an m5.large, Infracost immediately alerts us to the spike in monthly costs and$$CO_2e$$emissions. Having this visibility empowers developers to make informed architectural choices—such as opting for Graviton instances or gp3 storage—directly impacting the business's bottom line and sustainability goals.


Conclusion: The Future of Infrastructure is Conscious

Implementing FinOps is not just about reducing the bill at the end of the month; it’s about fostering a culture of accountability and transparency. Throughout this lab, we’ve seen that it is entirely possible to bridge security (via OIDC), governance (via Tags), and cost visibility directly within the development lifecycle.By bringing cost estimation into the Pull Request, we eliminate the financial "blind spot."
Developers evolve from simply consuming resources to becoming conscious architects, capable of pivoting toward more efficient solutions—such as Graviton instances or gp3 storage—before a single cent is even spent.This project serves as a practical example of how technology can be leveraged to build more sustainable and well-managed systems.
Ultimately, every $CO_2e$ saved and every dollar optimized contributes to a more mature and resilient operation.

I hope this guide assists fellow students and professionals on their cloud journey! 🚀


📂 Project Repository

All the code detailed in this article, including the networking and compute modules and the GitHub Actions workflow, is available on my GitHub. Feel free to clone, test, and contribute!