Skip to main content
Pulumi logo Pulumi logo
  1. Docs
  2. Infrastructure as Code
  3. Guides
  4. Basics
  5. Language Essentials
  6. Conditionals

Conditionals

    A conditional decides whether to do something, or which of two things to do, based on a value you already know. You use this constantly in HCL, usually without calling it a conditional: the count = var.enabled ? 1 : 0 idiom is a conditional wearing a resource-repetition costume. A general-purpose language gives you the if statement directly, so you don’t have to route the decision through a resource count.

    Where you have seen this before

    Pulumi YAML has no native conditional, so YAML programs work around the absence with fn::select or by omitting a resource entirely from the file for a given stack. Terraform HCL’s idiom is the conditional count:

    resource "aws_s3_bucket" "backups" {
      count  = var.environment == "production" ? 1 : 0
      bucket = "app-backups"
    }
    

    Everything downstream that used to reference aws_s3_bucket.backups now has to account for it being a list of zero or one items. That’s the tell that HCL is simulating a conditional with a loop, because it doesn’t have a real one.

    The syntax

    A general-purpose language has if/else directly, plus a conditional (ternary) expression for picking between two values. Go doesn’t have a ternary operator, so an if is the idiom there for both cases.

    const instanceSize = environment === "production" ? "m5.large" : "t3.micro";
    
    if (environment === "production") {
      // ...
    }
    
    instance_size = "m5.large" if environment == "production" else "t3.micro"
    
    if environment == "production":
        ...
    
    instanceSize := "t3.micro"
    if environment == "production" {
    	instanceSize = "m5.large"
    }
    
    var instanceSize = environment == "production" ? "m5.large" : "t3.micro";
    
    if (environment == "production")
    {
        // ...
    }
    
    var instanceSize = environment.equals("production") ? "m5.large" : "t3.micro";
    
    if (environment.equals("production")) {
        // ...
    }
    

    Pulumi YAML has no if or ternary expression. fn::select picks a value out of a list by a 0-based integer index, which stands in for a two-way choice when that index itself comes from config:

    config:
      isProduction:
        type: integer
    variables:
      instanceSize:
        fn::select:
          - ${isProduction}
          - - t3.micro
            - m5.large
    

    There’s no way to skip creating a resource entirely from YAML; that requires a general-purpose language or a component.

    HCL has a ternary expression but no if statement, so both branching on a value and deciding whether to create a resource at all go through the conditional expression, the second one via count:

    locals {
      instance_size = var.environment == "production" ? "m5.large" : "t3.micro"
    }
    
    resource "aws_s3_bucket" "backups" {
      count  = var.environment == "production" ? 1 : 0
      bucket = "app-backups"
    }
    

    In a Pulumi program

    Deciding whether to create a resource at all, such as a backup bucket that only exists in production, is a plain if around the resource declaration. pulumi.getStack() returns the current stack name, which is the language equivalent of the stack-scoped variables you’d otherwise branch on in HCL:

    import * as pulumi from "@pulumi/pulumi";
    import * as aws from "@pulumi/aws";
    
    if (pulumi.getStack() === "production") {
      new aws.s3.Bucket("app-backups");
    }
    
    import pulumi
    import pulumi_aws as aws
    
    if pulumi.get_stack() == "production":
        aws.s3.Bucket("app-backups")
    
    package main
    
    import (
    	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
    	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
    )
    
    func main() {
    	pulumi.Run(func(ctx *pulumi.Context) error {
    		if ctx.Stack() == "production" {
    			if _, err := s3.NewBucket(ctx, "app-backups", nil); err != nil {
    				return err
    			}
    		}
    		return nil
    	})
    }
    
    using Pulumi;
    using Pulumi.Aws.S3;
    
    return await Deployment.RunAsync(() =>
    {
        if (Deployment.Instance.StackName == "production")
        {
            var backups = new Bucket("app-backups");
        }
    });
    
    import com.pulumi.Pulumi;
    import com.pulumi.aws.s3.Bucket;
    
    public class App {
        public static void main(String[] args) {
            Pulumi.run(ctx -> {
                if (ctx.stackName().equals("production")) {
                    var backups = new Bucket("app-backups");
                }
            });
        }
    }
    

    Pulumi YAML has no way to skip declaring a resource based on a condition; every resource in the file is always created. Reaching for a general-purpose language, or a component someone already wrote in one, is the way to make resource creation itself conditional.

    resource "aws_s3_bucket" "backups" {
      count  = terraform.workspace == "production" ? 1 : 0
      bucket = "app-backups"
    }
    

    What to watch out for

    You can’t branch an if statement on a resource output. An output’s value isn’t known while your program is running, so a comparison like if (bucket.arn === "...") doesn’t do what it looks like it does. Branch on values you actually know when the program runs: stack names, configuration, and plain inputs. If a decision genuinely depends on a value that only exists after a resource is created, that decision has to happen inside apply, not in an if statement; see working with outputs for how that works.

    Frequently asked questions

    How do I make a resource conditional in Pulumi?

    Wrap the resource declaration in a plain if statement in your programming language. There’s no special conditional-resource construct to learn: the same branching you already use for any other decision in your code decides whether Pulumi sees the resource declaration at all, using ordinary values like stack configuration.

    What replaces count = 0 in Pulumi?

    Nothing special is needed; an ordinary if statement takes its place. Because you’re working with a real language rather than a declarative block, references to a conditionally created resource stay single values instead of becoming zero-or-one-element lists the way Terraform’s count produces, which keeps the rest of your program simpler.

    Can I branch on a resource output?

    No, not directly. A resource output isn’t known while your program runs, so an if can only branch on values known at that time, such as the stack name, configuration, or plain inputs. If a decision genuinely depends on a value produced by another resource, make it inside an apply callback instead of at the top level of your program.

    Next steps

    Continue to loops and iteration to see how a for loop replaces count and for_each for creating multiple resources.

      The infrastructure as code platform for any cloud.