(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisbon

How to perform automatic Terraform rollback in CI/CD: step by step

João Barros 27 de September de 2026 4 min read

This tutorial explains how to implement an automatic rollback for deployments made with Terraform in CI/CD pipelines, useful to protect infrastructure when post-deploy checks fail. You will learn why to perform rollback and how to automate the reversal using GitHub Actions and remote state.

Prerequisites

  • Azure account and a storage account with a container for the Terraform backend (or another supported remote backend).
  • GitHub repository with simple Terraform code (providers and a minimal resource).
  • GitHub Actions enabled and a secret with credentials to access the backend (e.g.: AZURE_CREDENTIALS).
  • Basic knowledge of Terraform (init, plan, apply) and YAML for Actions.

Step 1: understand the rollback strategy

Why: Terraform keeps state that represents the actual state of resources. An automatic rollback can revert applied changes if external checks fail (tests, smoke tests). The strategy here is: take a snapshot of the state before apply, apply, run checks; if there is a failure, restore the snapshot as the state and re-apply to revert.

Step 2: create a state snapshot before apply

Explanation: we will copy the remote state file to a file with a timestamp in the backend (or export locally). In the example we use the Azure CLI to copy the blob that contains the state.

# exemplo: guardar snapshot do state em Azure Blob
az storage blob download --container-name tfstate --name prod.terraform.tfstate \
  --file /tmp/prod.terraform.tfstate --account-name mystorageaccount

Step 3: apply Terraform in the pipeline (plan + apply)

Explanation: run terraform init, terraform plan and automated terraform apply. The apply creates the changes that may require rollback.

terraform init -backend-config="storage_account_name=mystorageaccount"
terraform plan -out=plan.tfplan
terraform apply -input=false plan.tfplan

Step 4: run post-deploy checks

Explanation: here we run smoke tests, endpoint checks, integrations or policy tests. If these checks fail, we trigger the rollback.

# Exemplo simples de verificação: HTTP 200 numa API
status=$(curl -s -o /dev/null -w "%{http_code}" https://api.exemplo.local/health)
if [ "$status" -ne 200 ]; then
  exit 1
fi

Step 5: restore the state for rollback

Explanation: if checks detect a failure, we restore the state to the saved snapshot and re-apply so that Terraform reconciles and removes the undesired changes. In the Azure Blob backend, upload the snapshot file to replace the current state.

# Substituir o state remoto pelo snapshot
az storage blob upload --container-name tfstate --name prod.terraform.tfstate \
  --file /tmp/prod.terraform.tfstate --account-name mystorageaccount --overwrite

# Re-aplicar para reconciliar a reversão
terraform init -backend-config="storage_account_name=mystorageaccount"
terraform apply -auto-approve

Step 6: integrate everything into a GitHub Actions

Explanation: create a workflow that chains the steps: snapshot -> apply -> checks -> (rollback if necessary). We provide a minimal example job that uses az cli and terraform.

name: terraform-deploy-with-rollback
on: [push]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Azure Login
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}
      - name: Download state snapshot
        run: az storage blob download --container-name tfstate --name prod.terraform.tfstate \
              --file /tmp/prod.terraform.tfstate --account-name mystorageaccount
      - name: Terraform Init
        run: terraform init -backend-config="storage_account_name=mystorageaccount"
      - name: Terraform Plan
        run: terraform plan -out=plan.tfplan
      - name: Terraform Apply
        run: terraform apply -input=false plan.tfplan
      - name: Run smoke tests
        run: |
          status=$(curl -s -o /dev/null -w "%{http_code}" https://api.exemplo.local/health)
          if [ "$status" -ne 200 ]; then
            echo "Smoke tests failed, starting rollback"
            az storage blob upload --container-name tfstate --name prod.terraform.tfstate \
              --file /tmp/prod.terraform.tfstate --account-name mystorageaccount --overwrite
            terraform apply -auto-approve
            exit 1
          fi

Verify the result

How to confirm: after running the workflow, check the job logs in GitHub Actions. If the checks pass, the infrastructure should reflect the new state. If there is a failure, confirm that the Terraform state blob was restored and that resources were reverted. Use the Azure CLI to list resources and compare with the expected state.

Conclusion

Implementing automatic rollback with Terraform and GitHub Actions increases deployment resilience: it saves a snapshot of the state, applies changes and automatically reverts if checks fail. Next steps: add locking (state locking), encrypt snapshots and test the rollback in staging environments. Tip: start with a simple resource and validate the process before applying in production — what automated test would make you more confident?