Day 8 of #30DaysOfTerraform — Terraform Meta-Arguments: Writing Dynamic Infrastructure

#30daysofawsterraform
Day 8 was one of those days where you suddenly see Terraform not just as a way to describe infrastructure, but as a tool that can generate it — based on patterns and inputs instead of copy-paste blocks.
Up until now, each AWS resource we created lived inside its own block. Want two S3 buckets? You wrote two blocks. Need three EC2 instances? That meant three resource definitions. That works at first, but as soon as you start thinking about scale, you see its limitations. On Day 8, I learned how Terraform’s meta-arguments — especially count, for_each, and depends_on — change that game entirely.
What Meta-Arguments Really Do
Meta-arguments are special arguments built into Terraform itself — not part of a provider like AWS. They let you control how many resources are created and in what order, without repeating block definitions.

How Terraform uses meta-arguments to dynamically create and order infrastructure.
Before Day 8, I might write:
resource "aws_s3_bucket" "bucket1" {
bucket = "my-app-bucket-1"
tags = var.tags
}
resource "aws_s3_bucket" "bucket2" {
bucket = "my-app-bucket-2"
tags = var.tags
}
That’s simple and clear — until you need ten buckets. It’s then that repetition gets ugly, error-prone, and hard to maintain.
Meta-arguments give you a better pattern.
Leveraging count for Repetition
The count meta-argument lets you turn one resource block into many:
resource "aws_s3_bucket" "buckets" {
count = length(var.bucket_names)
bucket = var.bucket_names[count.index]
tags = var.tags
}
Here’s what’s nice about this:
One block generates multiple resources
count.indexgives each instance its placeYou can control names through variables
This makes the infrastructure elastic without duplication.
When for_each Makes More Sense
for_each is similar to count, but more stable when your list of values doesn’t map cleanly to numerical indexes.
resource "aws_s3_bucket" "buckets" {
for_each = toset(var.bucket_names)
bucket = each.value
tags = var.tags
}
This pattern is especially useful when:
You need stable resource identity over time
The order may change but you don’t want Terraform to recreate everything
You derive the list from maps or sets
That predictability matters in production.
Controlling Dependencies with depends_on
Terraform usually figures out dependencies automatically — based on references in the code. But there are real scenarios where the order matters even when there’s no direct reference.
For example:
An S3 bucket must exist before a policy attache
A VPC must be fully created before subnets
Custom IAM roles need to be in place before resources depend on them
In these cases, depends_on gives you explicit control:
resource "aws_s3_bucket" "example" {
bucket = "my-tf-bucket"
tags = var.tags
depends_on = [
aws_vpc.main
]
}
This forces Terraform to create the VPC before the bucket — even if otherwise they don’t depend on each other.
What This Changes in Your Terraform Workflow
By the end of Day 8’s exercise, a few clear shifts happened in my thinking:
I no longer write the same resource block 5–10 times accidentally
I treat Terraform like a mini programming language for infrastructure
Dependencies become safer to manage, not accidents waiting to happen
I see patterns in infrastructure that can be abstracted and repeated consistently
This is where Terraform starts feeling smart, not just convenient.
A Real-World Example (Beyond S3)
Imagine you’re provisioning multiple security groups, or spinning up clusters with a variable number of instances. With count or for_each, you can scale your HCL just like you scale resources:
Create n subnets dynamically
Generate multiple IAM users from a list
Provision network ACLs for each AZ
Build tags or naming conventions that adapt by environment or workspace
These patterns are the difference between a one-off script and infrastructure that grows with requirement changes.
Takeaway
Day 8 wasn’t just a lesson on Terraform syntax — it was about thinking differently:
countandfor_eachreplace repetition with pattern-based infrastructuredepends_ongives you safety when implicit linking isn’t obviousTerraform starts to feel like a declarative automation language, not just a config tool
Once you stop copying code and start writing patterns with meta-arguments, your infrastructure becomes cleaner, safer, and closer to real engineering.




