---
title: Variables
url: /docs/iac/guides/basics/language-essentials/variables/
---


A variable gives a name to a value so you can reuse it and refer to it later.
Every configuration language you already use has a version of this: a `locals`
block in HCL, a `variables:` section in Pulumi YAML. In a general-purpose
language, naming a value is the most basic thing you do, and it works the same
way whether the value is a string, a number, or the result of creating a
resource.

## Where you have seen this before

In Pulumi YAML, `variables` names a value once so you can reference it
elsewhere in the same file:

```yaml
variables:
  bucketName: my-app-data
resources:
  bucket:
    type: aws:s3:Bucket
    properties:
      bucket: ${bucketName}
```

In Terraform HCL, a `locals` block does the same thing, and `${...}`
interpolation substitutes it into a string:

```hcl
locals {
  bucket_name = "my-app-data"
}

resource "aws_s3_bucket" "bucket" {
  bucket = "${local.bucket_name}"
}
```

## The syntax

In a general-purpose language, you declare a variable and assign it a value in
one statement. Most Pulumi languages infer the type from the value, so you
rarely write the type out yourself.

<!-- chooser: language -->

<!-- option: typescript -->
```typescript
const bucketName = "my-app-data";
const replicaCount = 3;

```

<!-- /option -->

<!-- option: python -->
```python
bucket_name = "my-app-data"
replica_count = 3

```

<!-- /option -->

<!-- option: go -->
```go
bucketName := "my-app-data"
replicaCount := 3

```

<!-- /option -->

<!-- option: csharp -->
```csharp
var bucketName = "my-app-data";
var replicaCount = 3;

```

<!-- /option -->

<!-- option: java -->
```java
var bucketName = "my-app-data";
var replicaCount = 3;

```

<!-- /option -->

<!-- option: yaml -->
```yaml
variables:
  bucketName: my-app-data
  replicaCount: 3

```

<!-- /option -->

<!-- option: hcl -->
```hcl
locals {
  bucket_name   = "my-app-data"
  replica_count = 3
}

```

<!-- /option -->

<!-- /chooser -->

Building a string out of a variable works the way you'd expect from `${...}`
interpolation, just with each language's own syntax: template literals in
TypeScript, f-strings in Python, `fmt.Sprintf` in Go, `$"..."` in C#, and
`String.format` in Java.

<!-- chooser: language -->

<!-- option: typescript -->
```typescript
const label = `${bucketName}-${replicaCount}`;

```

<!-- /option -->

<!-- option: python -->
```python
label = f"{bucket_name}-{replica_count}"

```

<!-- /option -->

<!-- option: go -->
```go
label := fmt.Sprintf("%s-%d", bucketName, replicaCount)

```

<!-- /option -->

<!-- option: csharp -->
```csharp
var label = $"{bucketName}-{replicaCount}";

```

<!-- /option -->

<!-- option: java -->
```java
var label = String.format("%s-%d", bucketName, replicaCount);

```

<!-- /option -->

<!-- option: yaml -->
```yaml
variables:
  label: ${bucketName}-${replicaCount}

```

<!-- /option -->

<!-- option: hcl -->
```hcl
locals {
  label = "${local.bucket_name}-${local.replica_count}"
}

```

<!-- /option -->

<!-- /chooser -->

## In a Pulumi program

Stack configuration is the language equivalent of a `Pulumi.<stack>.yaml`
value you'd otherwise reference directly. You read it into a variable with
`pulumi.Config` and use it the same way you'd use any other variable. Set the
value first, since `config.require` fails if it isn't set:

```bash
pulumi config set environment production
```

<!-- chooser: language -->

<!-- option: typescript -->
```typescript
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const config = new pulumi.Config();
const environment = config.require("environment");

const bucket = new aws.s3.Bucket(`data-${environment}`);

```

<!-- /option -->

<!-- option: python -->
```python
import pulumi
import pulumi_aws as aws

config = pulumi.Config()
environment = config.require("environment")

bucket = aws.s3.Bucket(f"data-{environment}")

```

<!-- /option -->

<!-- option: go -->
```go
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		cfg := config.New(ctx, "")
		environment := cfg.Require("environment")

		_, err := s3.NewBucket(ctx, fmt.Sprintf("data-%s", environment), nil)
		return err
	})
}

```

<!-- /option -->

<!-- option: csharp -->
```csharp
using Pulumi;
using Pulumi.Aws.S3;

return await Deployment.RunAsync(() =>
{
    var config = new Config();
    var environment = config.Require("environment");

    var bucket = new Bucket($"data-{environment}");
});

```

<!-- /option -->

<!-- option: java -->
```java
import com.pulumi.Pulumi;
import com.pulumi.Config;
import com.pulumi.aws.s3.Bucket;

public class App {
    public static void main(String[] args) {
        Pulumi.run(ctx -> {
            var config = ctx.config();
            var environment = config.require("environment");

            var bucket = new Bucket("data-" + environment);
        });
    }
}

```

<!-- /option -->

<!-- option: yaml -->
```yaml
config:
  environment:
    type: string
resources:
  bucket:
    type: aws:s3:Bucket
    properties:
      bucket: data-${environment}

```

<!-- /option -->

<!-- option: hcl -->
```hcl
variable "environment" {
  type = string
}

resource "aws_s3_bucket" "bucket" {
  bucket = "data-${var.environment}"
}

```

<!-- /option -->

<!-- /chooser -->

## What to watch out for

Not every value on a resource is a plain string or number you can interpolate
directly. Many resource properties are outputs: values Pulumi doesn't know
until the resource is actually created, such as a generated ARN or a load
balancer's DNS name. Ordinary string interpolation doesn't work on an output,
because the value isn't available when your program runs. See
[inputs and outputs](/docs/iac/concepts/inputs-outputs/) for how that model
works, and each language's interpolation helper, such as `pulumi.interpolate`
in TypeScript or `pulumi.Output.format()` in Python, for building strings out
of them.

## Next steps

Continue to [conditionals](/docs/iac/guides/basics/language-essentials/conditionals/)
to see how `if` statements replace `count`-based conditionals.

## Learn more

- [Configuration](/docs/iac/concepts/config/) for the full set of options for
  reading and validating stack configuration.

