WEBINARLive webinar: Terraform in Buddy, Oct 21st.Terraform: plan, approve, apply with state in Buddy. Live on October 21st.Save your seat

State backends

View as Markdown

Terraform stores what it manages in a state. Without a persistent state, every run would create the infrastructure from scratch. Each Terraform action has a backend setting that tells Buddy where the state is kept:

backend.type Where the state is What Buddy adds
ARTIFACT A Buddy artifact The backend configuration and credentials
AMAZON An S3 backend declared in your code AWS credentials from an integration
GOOGLE A GCS backend declared in your code Google credentials from an integration
CUSTOM (default) The backend declared in your code Nothing
Warning
Set the same backend in every action that works on one state: Plan, Apply, and Drift Detection. Otherwise Apply works on a different state than the one that was planned.

ARTIFACT

The state is stored in a Buddy artifact. You don't need a bucket, a lock table, or any credentials.

Requirements

  • The artifact and its version must already exist. Buddy doesn't create them, and the action fails with not found if either is missing.
  • The artifact must be of type Bucket, with Access control set to Buddy Auth.
  • The pipeline needs read-write access to the artifact.
  • Your code must not declare a backend block.
yaml
backend: type: ARTIFACT artifact: infra-state artifact_version: prod

Image loading...Backend tab with Buddy Artifact selected

How it works

Before running the tool, Buddy writes buddy_backend.tf to the working directory:

hcl
terraform { backend "http" {} }

It also sets the HTTP backend variables:

Variable Value
TF_HTTP_ADDRESS, TF_HTTP_LOCK_ADDRESS, TF_HTTP_UNLOCK_ADDRESS <artifact version URL>/tf.tfstate
TF_HTTP_USERNAME The pipeline ID
TF_HTTP_PASSWORD A token of the pipeline run

One artifact version holds one state file, tf.tfstate, which is overwritten on every apply. To keep separate states, for example per environment, use separate versions (dev, staging, prod) or separate artifacts.

Locking

The artifact backend supports state locking. While one action holds the lock, another one working on the same state waits or fails, depending on -lock-timeout in additional_args.

Size limit

A state file can be up to 2 GB. To raise the limit, contact support.

Moving an existing state to an artifact

Buddy doesn't migrate state automatically. To move an existing state:

  1. Make sure nothing is running against the old state.
  2. Download it from the old backend: terraform state pull > tf.tfstate.
  3. Upload tf.tfstate to the root of the artifact version - in the UI or with the REST API.
  4. Remove the backend block from your code and set backend.type to ARTIFACT.
  5. Run a Plan. If the state was moved correctly, it shows no changes.

State name in the Terraform CLI action

In the Terraform CLI action, state_name changes the file name to <state_name>.tfstate. Plan, Apply, and Drift Detection always use tf.tfstate.

AMAZON

Your code declares an s3 backend. Buddy exports the credentials of the selected AWS integration to the container:

hcl
terraform { backend "s3" { bucket = "my-terraform-state" key = "prod/terraform.tfstate" region = "eu-central-1" } }
yaml
backend: type: AMAZON integration: my-aws region: eu-central-1

The exported variables are AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, and AWS_DEFAULT_REGION, plus AWS_ACCOUNT_ID, AWS_USER, and AWS_USER_ARN for information. The AWS provider reads the same variables, so the integration also authenticates your AWS resources. The integration can use OIDC instead of static keys.

GOOGLE

Your code declares a gcs backend. Buddy writes the key of the selected Google Service Account integration to a file and sets GOOGLE_CREDENTIALS. The Google provider reads it too.

yaml
backend: type: GOOGLE integration: my-gcp

CUSTOM

Buddy leaves the backend to your code. Use it for any backend Terraform supports, for example azurerm, http, pg, remote, or S3 with credentials you provide yourself. Pass the credentials as variables, for example ARM_CLIENT_ID and ARM_CLIENT_SECRET for Azure.

Last modified on Oct 19, 2026