Skip to content

Ephemeral Values

When working with sensitive data in Terraform — passwords, API keys, tokens — you might reach for sensitive = true on a variable or output. This prevents the value from appearing in CLI output, but it does not protect the value in state. Terraform still writes the plain-text value into the state file, which means anyone with access to the state backend can read it.

Ephemeral values and write-only arguments address this gap by ensuring that sensitive data never reaches the state file at all.


Ephemeral values, introduced in Terraform 1.10, are values that exist only during a Terraform operation (plan or apply) and are never persisted to state or plan files. Once the operation completes, the value is discarded.

This is fundamentally different from sensitive = true, which only controls display. An ephemeral value is never written to disk, making it suitable for secrets that should not appear in state under any circumstances.

You can mark an input variable as ephemeral so that its value is never stored in state. This is useful for secrets that are passed in at runtime — for example, from a CI/CD pipeline or environment variable.

variable "db_password" {
type = string
ephemeral = true
}

An ephemeral variable behaves like any other variable during the operation, but Terraform refuses to write its value to state or plan files. If you try to use an ephemeral variable in a context that would persist it (such as a regular resource argument), Terraform raises an error.

Outputs can also be marked as ephemeral. This is useful when a module produces a secret that the calling configuration needs during the operation but should not store.

output "generated_password" {
value = ephemeral.random_password.db.result
ephemeral = true
}

An ephemeral output is available to the parent module during the current operation, but Terraform does not write it to state. This means it cannot be read after the operation completes — for example, via terraform output.

Ephemeral resources are a new resource type that produces values existing only for the duration of a Terraform operation. They are declared with the ephemeral keyword instead of resource.

ephemeral "random_password" "db" {
length = 32
special = true
}

Each time Terraform runs, the ephemeral resource produces a fresh value. Nothing is stored in state — there is no create, update, or delete lifecycle. The value is generated, used where needed, and then discarded.

Because ephemeral values are never persisted, Terraform restricts where they can appear. You can use ephemeral values in the following contexts:

  • Provider configuration blocks — pass secrets directly to provider authentication without storing them in state.
  • Provisioner blocks — use ephemeral values in local-exec or remote-exec provisioners.
  • Other ephemeral resources — one ephemeral resource can reference another.
  • Write-only arguments — resource arguments that accept a value but never read it back from state (see below).

Attempting to use an ephemeral value in a regular resource argument that would be persisted to state results in a validation error. This is by design — Terraform enforces the boundary so that secrets cannot accidentally leak into state.

Write-only arguments, introduced in Terraform 1.11, extend the ephemeral concept to individual resource arguments. A write-only argument accepts a value during apply and sends it to the provider API, but the provider never reads the value back and Terraform never stores it in state.

This solves a long-standing problem: even with sensitive = true, resource arguments like database passwords are stored in state because Terraform needs to detect drift. Write-only arguments break that cycle — the value is sent to the API and then forgotten.

Providers opt in to write-only arguments on a per-attribute basis. When a provider marks an argument as write-only, Terraform:

  1. Sends the value to the provider during create or update operations.
  2. Does not store the value in state.
  3. Does not read the value back during refresh.

Because the value is not in state, Terraform cannot detect drift on write-only arguments. To handle password rotation and similar scenarios, providers typically pair a write-only argument with a version counter.

Here is a practical example using an ephemeral resource to generate a database password and pass it to an AWS RDS instance via a write-only argument:

ephemeral "random_password" "db" {
length = 32
special = true
}
resource "aws_db_instance" "main" {
engine = "mysql"
instance_class = "db.t3.micro"
allocated_storage = 20
db_name = "appdb"
username = "admin"
password_wo = ephemeral.random_password.db.result
password_wo_version = 1
}

The password_wo argument sends the generated password to the RDS API, but Terraform never writes it to state. When you need to rotate the password, increment password_wo_version — this tells Terraform to send the new value to the API even though it cannot compare against the previous one.

Ephemeral resources and write-only arguments require provider-level support. At the time of writing, the following major providers have added support:

  • AWS (hashicorp/aws) — write-only arguments on resources like aws_db_instance (password_wo), aws_secretsmanager_secret_version, and others.
  • Azure (hashicorp/azurerm) — write-only arguments for secrets and credentials across several resources.
  • GCP (hashicorp/google) — write-only arguments for sensitive fields in database and secret manager resources.
  • Kubernetes (hashicorp/kubernetes) — write-only arguments for secret data.

Provider support is expanding with each release. Check the provider changelog or documentation to confirm which resources and arguments support write-only behaviour in your version.

Ephemeral values and write-only arguments close the gap between marking a value as sensitive and actually keeping it out of state. Ephemeral variables, outputs, and resources ensure that secrets exist only for the duration of an operation, while write-only arguments let providers accept sensitive data without ever persisting it. Together, they give you a practical path to managing secrets in Terraform without exposing them in state files.