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

推荐订阅源

Security Latest
Security Latest
D
DataBreaches.Net
The Register - Security
The Register - Security
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
F
Full Disclosure
Engineering at Meta
Engineering at Meta
The GitHub Blog
The GitHub Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
P
Proofpoint News Feed
D
Docker
Y
Y Combinator Blog
T
The Blog of Author Tim Ferriss
云风的 BLOG
云风的 BLOG
G
Google Developers Blog
I
InfoQ
H
Help Net Security
MongoDB | Blog
MongoDB | Blog
Recent Announcements
Recent Announcements
L
Lohrmann on Cybersecurity
T
The Exploit Database - CXSecurity.com
Recorded Future
Recorded Future
G
GRAHAM CLULEY
Microsoft Security Blog
Microsoft Security Blog
WordPress大学
WordPress大学
L
LINUX DO - 热门话题
阮一峰的网络日志
阮一峰的网络日志
The Cloudflare Blog
Help Net Security
Help Net Security
雷峰网
雷峰网
W
WeLiveSecurity
GbyAI
GbyAI
N
News and Events Feed by Topic
L
LINUX DO - 最新话题
T
Tailwind CSS Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
V
Vulnerabilities – Threatpost
V
V2EX
Application and Cybersecurity Blog
Application and Cybersecurity Blog
M
MIT News - Artificial intelligence
J
Java Code Geeks
Microsoft Azure Blog
Microsoft Azure Blog
Last Week in AI
Last Week in AI
Hugging Face - Blog
Hugging Face - Blog
Cisco Talos Blog
Cisco Talos Blog
Webroot Blog
Webroot Blog
AI
AI
S
Security @ Cisco Blogs
Jina AI
Jina AI
The Last Watchdog
The Last Watchdog
Google DeepMind News
Google DeepMind News

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
Terraform outputs.tf Explained: What It Is, When to Use It, and When to Skip It
Tanseer · 2026-06-23 · via DEV Community

Who This Is For

If you are learning Terraform and have come across outputs.tf in project structures or tutorials but are not fully clear on what it actually does or why it exists, this blog is for you.

We will start from the basics and build up to how outputs work across modules, what they look like in practice, and the rules around where they can and cannot be used. Every term will be explained along the way.


What Is an Output in Terraform?

When Terraform creates infrastructure, it stores everything it knows about that infrastructure in a file called the state file. The state file is Terraform's database. It tracks every resource, every attribute, every ID — everything.

But the state file is not something you read directly. It is large, it is internal, and most of the values in it are not things you care about day to day.

Outputs are a way to surface specific values from that state file — the ones you actually need. You decide what gets exposed. Everything else stays internal.

A good way to think about it:

State file = the entire database.

Outputs = a view on top of that database that exposes only what you chose to make visible.

Outputs do not add new information. They do not change what Terraform tracks. They simply choose what to surface from what already exists.


The Three Contexts Where Outputs Are Used

Outputs are not just for one purpose. They serve three distinct purposes depending on where you use them. Understanding the difference between these three will make the entire concept click.


Context 1: Passing Values Between Modules in the Same Project

This is the most common use case, and the one you will use in almost every real Terraform project.

Imagine your project has two modules: a database module and a backend module. The database module creates an RDS instance and stores credentials in AWS Secrets Manager. The backend module is a Lambda function that needs to connect to that database. To do that, it needs the ARN (unique identifier) of the secret.

But here is the problem. Module internals are private. A resource defined inside modules/database/main.tf is not visible anywhere outside that module. It is intentionally hidden. You cannot just reference it from another module directly.

This is where outputs.tf comes in. The database module uses outputs.tf to explicitly expose the values it wants to share. The backend module then receives those values as input variables.

The wiring between them happens in your environment file, for example environments/dev/main.tf. That file is the connection layer. It takes what one module exposes and passes it as input to another.

The flow looks like this:

modules/database/outputs.tf
        |
        v
environments/dev/main.tf   (the wiring layer)
        |
        v
modules/backend/variables.tf

Here is what that looks like in code:

# modules/database/outputs.tf
output "secret_arn" {
  value = aws_secretsmanager_secret.db_credentials.arn
}

output "secret_name" {
  value = aws_secretsmanager_secret.db_credentials.name
}

# environments/dev/main.tf
module "database" {
  source = "../../modules/database"
}

module "backend" {
  source     = "../../modules/backend"
  secret_arn  = module.database.secret_arn
  secret_name = module.database.secret_name
}

# modules/backend/variables.tf
variable "secret_arn" {}
variable "secret_name" {}

The database module is a black box. variables.tf is what it accepts as input. main.tf is its internal implementation. outputs.tf is what it hands back out. Nothing inside the module leaks out unless you explicitly put it in outputs.tf.


Context 2: Displaying Values in the Terminal After Apply

Outputs defined in the root module, meaning the environment folder like environments/dev, are printed to the terminal after terraform apply completes.

This is purely for you as the person running the deployment. It is a convenience feature so you do not have to go hunting through the AWS console for values you commonly need.

Good candidates for terminal outputs are things like:

The API Gateway URL your backend is reachable at.

The Amplify URL where your frontend is deployed.

The RDS endpoint for your database.

# environments/dev/outputs.tf
output "api_gateway_url" {
  value = module.backend.api_url
}

output "amplify_url" {
  value = module.frontend.app_url
}

After apply, these print cleanly to your terminal:

Outputs:

api_gateway_url = "https://abc123.execute-api.ap-south-1.amazonaws.com/dev"
amplify_url     = "https://main.abc123.amplifyapp.com"

No digging through the console. The values are right there.


Context 3: Sharing Values Across Completely Separate Terraform Projects

Sometimes infrastructure is split across multiple completely separate Terraform projects, each with their own state file. A networking team might manage VPCs in one project. An application team might manage Lambda functions in another. The application team needs the VPC ID from the networking project.

This is handled using something called terraform_remote_state. It is a data source (a way to read information from outside the current project) that reads another project's state file and exposes its outputs.

data "terraform_remote_state" "networking" {
  backend = "s3"
  config = {
    bucket = "company-tfstate"
    key    = "networking/terraform.tfstate"
    region = "ap-south-1"
  }
}

# Now you can use:
data.terraform_remote_state.networking.outputs.vpc_id

One important detail here: terraform_remote_state can only access values that were explicitly defined as outputs in the other project. It cannot reach into the raw state and pull arbitrary values. If the networking team did not put the VPC ID in their outputs.tf, you cannot get it from here.

This reinforces the same rule: outputs are the only gateway for values to leave a Terraform boundary, whether that boundary is a module or an entire separate project.

This pattern does not apply if your entire infrastructure lives in one root, which is the case for smaller projects. But it is a real and widely used pattern in team environments.


Where Outputs Cannot Be Used

This is important. Outputs work during the plan and apply phase, when Terraform is evaluating your configuration and building infrastructure. But not every file in your project is evaluated at that phase.

Two files are evaluated earlier, during the init phase, before any HCL evaluation happens:

backend.tf — This is where you configure where Terraform stores its state file, for example an S3 bucket. Terraform reads this file during terraform init, before it knows anything about your resources or variables. Everything here must be a hardcoded string. You cannot reference an output, a variable, or a local.

providers.tf — This is where you configure your cloud provider, for example the AWS region and profile. This is also read during init. Same restriction. Hardcode everything here.

Trying to use a variable or output in either of these files will cause Terraform to throw an error, and the reason is always the same: those values are not available yet at init time.

Here is a simple way to remember the two phases:

Init phase reads backend.tf and providers.tf statically. Downloads providers. Sets up the backend. No HCL logic allowed.

Plan and Apply phase evaluates everything else. Outputs, variables, locals, data sources, resource references — all of this works here.


Why You Cannot Just Skip outputs.tf and Read the State Directly

A common question when learning this is: the state file already has all the values, why do I need outputs at all?

There are two reasons.

Within a module, resources are private by design. Terraform intentionally encapsulates module internals so that modules are independent and reusable. You cannot reach into modules/database/main.tf from environments/dev/main.tf and reference a resource directly. The module must explicitly hand that value out through outputs.tf. This is the same reason functions in a programming language return values instead of letting callers read internal variables directly.

Across separate roots, terraform_remote_state only exposes outputs. There is no mechanism to read arbitrary resource attributes from another project's state file. Outputs are the only thing that crosses that boundary.


When outputs.tf Is Optional

Not every module needs an outputs.tf. The rule is straightforward.

If nothing downstream needs a value from your module, there is nothing to expose. The outputs file is optional.

A common example is a frontend module in a project. If the frontend module deploys an Amplify app and no other module needs the Amplify URL as an input, then outputs.tf in the frontend module is not needed. The URL might still be shown in the terminal via the root module's outputs, but the frontend module itself does not need to expose anything.

The question to ask before adding any output is:

Who is the consumer of this value, and how will they read it?

If the answer is nobody, the output does not belong. Adding outputs that nothing consumes is just noise in your codebase.


A Quick Reference

Here is everything in one place:

Outputs between modules: use outputs.tf in the source module, wire it in the environment's main.tf, receive it in the destination module's variables.tf.

Outputs in the terminal: define them in the root module's outputs.tf. They print after terraform apply.

Outputs across separate roots: use terraform_remote_state to read another project's outputs from its remote state file.

Outputs do not work in backend.tf or providers.tf because those are read during init before HCL evaluation.

You cannot skip outputs.tf because module internals are private and remote state only exposes outputs.

outputs.tf is optional when nothing downstream needs the module's values.


Conclusion

Outputs are one of those concepts in Terraform that seem small but are actually the backbone of how information flows through your infrastructure code. Once you understand that modules are black boxes and outputs are the only thing that leaves them, the entire system starts to make sense.

Before adding any output, always ask who the consumer is. That one question will keep your outputs intentional, your modules clean, and your project easy to follow.


Need Help?

If you are learning Terraform and have questions about project structure, modules, state management, or anything else, feel free to reach out.

Email me at khantanseer43@gmail.com