Terraform Conditional

Bits Lovers
Written by Bits Lovers on
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.

Bits Lovers

Bits Lovers

Professional writer and blogger. Focus on Cloud Computing.

Comments

comments powered by Disqus