Terraform Conditional
Terraform is a declarative language. That means you describe the desired state, and Terraform figures out how to get there. Unlike procedural languages, you don’t write step-by-step instructions.
This has advantages. Your code matches what actually runs in production. But some things that are trivial in a procedural language require a different approach in Terraform.
There’s No IF Block
Let me save you some searching: Terraform has no if statement block. You cannot write something like:
if (var.env == "prod") {
# not valid Terraform
}
The language simply doesn’t work that way. You work with what Terraform provides.
The Ternary Expression
If you’ve used C, JavaScript, or Python, you’ve seen this pattern:
<CONDITION> ? <TRUE_VALUE> : <FALSE_VALUE>
When the condition is true, you get the first value. When it’s false, you get the second. Terraform supports this syntax everywhere you can use an expression.
Example:
instance_type = var.environment == "prod" ? "t3.large" : "t3.micro"
That’s it. The same pattern works in outputs, variables, resource attributes—anywhere an expression is allowed.
Conditional Resource Creation
Here’s where things get practical. You often need to create different resources based on a variable. For example, deploying either a Network Load Balancer or an Application Load Balancer depending on environment.
You cannot conditionally skip a resource block. But you can use count to achieve the same result:
resource "aws_lb" "network_lb" {
count = var.load_balance_type == "network" ? 1 : 0
name = "${var.app_name}-nlb"
load_balancer_type = var.load_balance_type
subnets = split(",", var.lb_subnet_ids)
internal = var.enable_internal
enable_deletion_protection = true
}
resource "aws_lb" "alb" {
count = var.load_balance_type == "network" ? 0 : 1
name = "${var.env_name}-alb"
load_balancer_type = var.load_balance_type
security_groups = [aws_security_group.sg-alb.id]
subnets = split(",", var.lb_subnet_ids)
internal = true
access_logs {
bucket = var.bucket_logs
prefix = "bitslovers"
enabled = "true"
}
}
When load_balance_type is “network”, the first resource gets count = 1 and the second gets count = 0. Terraform creates only the NLB. When it’s something else, the reverse happens.
You reference the conditionally-created resource the same way as any other, but you need to account for the fact that it might not exist. If you try to access aws_lb.alb.dns_name when count = 0, Terraform will error.
Use the [0] indexer when you know the resource always exists, or conditional expressions to handle the case when it might not:
output "dns_name" {
description = "DNS from Application or Network Load Balancer"
value = var.load_balance_type == "network" ? aws_lb.network_lb[0].dns_name : aws_lb.alb[0].dns_name
}
Note the [0] index. This is required when referencing a resource created with count inside a ternary.
Conditional Modules
The same pattern works for entire modules:
module "lb_network" {
source = "./modules/lb-network"
count = var.load_balance_type == "network" ? 1 : 0
}
When the condition is false, the module is not instantiated. Any references to module.lb_network will fail unless you guard them.
Other Approaches
count is the most common solution, but two others exist:
Dynamic blocks let you conditionally generate nested blocks inside a resource. Useful when you need to add or remove sections within a resource based on a condition.
for_each with a set lets you create zero or one instance of a resource. The syntax differs but the effect is similar:
resource "aws_lb" "example" {
for_each = toset(var.create_lb ? ["create"] : [])
# ...
}
When create_lb is false, the set is empty and Terraform creates nothing.
What Hasn’t Changed
The ternary syntax, the count meta-argument, and the general approach to conditionals in Terraform all work the same as in 2021. HashiCorp has maintained backward compatibility here. The examples in this article still run on Terraform 1.x.
If you’re running older Terraform (pre-0.13), some syntax differs. But if you’re on anything remotely current, you’re fine.
The Bottom Line
Terraform conditionals require thinking in expressions rather than statements. You use ternary operators for conditional values and count for conditional resource creation. Once it clicks, it becomes natural. The key is remembering that everything is an expression that returns a value.
Comments