What Is a Terraform Output Value?
A Terraform output value is how your configuration shares information with the outside world. After terraform apply creates resources, outputs print the values you care about — the RDS endpoint to put in your application config, the S3 bucket name to set as an environment variable, the VPC ID for another Terraform configuration to reference.
Think of outputs as the return values of your Terraform configuration. Just as a function returns a value for its caller to use, an output makes an infrastructure attribute available for humans and other systems to consume.
At Hotstar, the networking team's Terraform configuration outputs the VPC ID and subnet IDs. The platform team's configuration reads those outputs via terraform_remote_state to know where to place EC2 instances — without duplicating or hardcoding any IDs.
+------------------------------------------+| resource "aws_db_instance" "main" { || identifier = "hotstar-prod-postgres" || } |+------------------------------------------+ | v+------------------------------------------+| output "rds_endpoint" { || value = aws_db_instance.main.address || } |+------------------------------------------+ | +-----------+-----------+ | | v v+---------------+ +---------------------------+| Terminal | | Other Terraform config || after apply: | | data "terraform_remote_ || rds_endpoint | | state" "network" {} || = "abc.rds.." | | data.terraform_remote_ || | | state.network.outputs || | | .rds_endpoint |+---------------+ +---------------------------+Declaring Outputs
# outputs.tf # Basic string outputoutput "s3_bucket_name" { description = "S3 bucket name — set as APP_DATA_BUCKET environment variable" value = aws_s3_bucket.app_data.id # .id is the bucket name for S3} # ARN output — for use in IAM policiesoutput "s3_bucket_arn" { description = "S3 bucket ARN — reference in IAM policy resource fields" value = aws_s3_bucket.app_data.arn} # Sensitive output — hidden in terminal, requires explicit flag to readoutput "db_connection_string" { description = "Full PostgreSQL connection string" value = "postgres://${aws_db_instance.main.username}@${aws_db_instance.main.endpoint}/${aws_db_instance.main.db_name}" sensitive = true} # Map output — group related valuesoutput "database" { description = "Database connection parameters for application configuration" value = { host = aws_db_instance.main.address port = aws_db_instance.main.port name = aws_db_instance.main.db_name endpoint = aws_db_instance.main.endpoint }} # List output — from count or for_each resourcesoutput "private_subnet_ids" { description = "Private subnet IDs — use in RDS subnet groups and EC2 placement" value = aws_subnet.private[*].id} # Computed output — derived from resource attributesoutput "app_url" { description = "Application URL — add this to your DNS records" value = "https://${aws_lb.main.dns_name}"}Reading Outputs
# Print all outputs after applyterraform output # Print one specific output (with type info and quotes)terraform output rds_endpoint # Print raw value — no quotes, for use in shell scriptsRDS_HOST=$(terraform output -raw rds_endpoint)echo "Database host: $RDS_HOST" # Print all outputs as machine-readable JSONterraform output -json # Read a sensitive output — requires -raw or -jsonterraform output -raw db_connection_string # Use output in a scriptBUCKET=$(terraform output -raw s3_bucket_name)aws s3 cp myfile.txt s3://$BUCKET/Outputs Between Configurations (Remote State)
Outputs are the mechanism for sharing infrastructure data between separate Terraform configurations:
# networking/outputs.tf — networking team exposes VPC detailsoutput "vpc_id" { value = aws_vpc.main.id} output "private_subnet_ids" { value = aws_subnet.private[*].id}# compute/main.tf — platform team reads networking outputs via remote statedata "terraform_remote_state" "networking" { backend = "s3" config = { bucket = "razorpay-terraform-state" key = "prod/networking/terraform.tfstate" region = "ap-south-1" }} resource "aws_instance" "app" { subnet_id = data.terraform_remote_state.networking.outputs.private_subnet_ids[0] # No hardcoded subnet IDs — always current from the networking state}Output Formatting Tips
# Output that includes computed expressionoutput "s3_console_url" { description = "Direct link to the S3 bucket in the AWS console" value = "https://s3.console.aws.amazon.com/s3/buckets/${aws_s3_bucket.data.id}"} # Output structured connection info as a JSON-friendly mapoutput "app_config" { description = "Environment variables to set in the application" value = { DB_HOST = aws_db_instance.main.address DB_PORT = tostring(aws_db_instance.main.port) S3_BUCKET = aws_s3_bucket.data.id AWS_REGION = data.aws_region.current.name ENVIRONMENT = var.environment }}Troubleshooting Outputs
| Error | Root Cause | Fix |
|---|---|---|
Error: Output refers to an undeclared resource |
Typo in resource address | Check resource type and name spelling |
Output shows (sensitive value) |
Output has sensitive = true |
Use terraform output -raw <name> |
Error: Unsupported attribute |
Wrong attribute name on resource | Check provider docs for valid attributes |
| Output missing after apply | Output block not in any .tf file | Add output block to outputs.tf and reapply |
| Remote state output not found | Spelling mismatch between configs | Check exact output name in source config |
PLACEMENT PRO TIP**Tip:** Add `terraform output -json` at the end of your CI/CD apply step and store the JSON as a build artifact. Downstream pipelines can read infrastructure values without re-running Terraform.
COMMON MISTAKE / WARNING**Common Mistake:** Outputting sensitive values without `sensitive = true`. Database passwords and connection strings will be printed to the terminal and logged in CI/CD unless marked sensitive. Always mark outputs that contain secrets.