Remote Back-End in Terraform

May 1, 2020

This article is also cross-posted in: DEV - 2020 - Remote back-end in Terraform

A "backend" in Terraform determines how the state is loaded and how an operation such as apply is executed.

By default, Terraform uses the "local" backend, which is the normal behavior of Terraform you're used to, but, if you're working in a team, or you don't want to keep sensitive information in your local disk, or you're working remotely, it's highly recommended to store this 'state' in the cloud, and we're going to see in this article how it can be done storing the backend in an S3 bucket.


To configure your remote state in Terraform, you need two instances:

  • An s3 bucket where the terraform.state file is stored.
  • A dynamo table with a lock id to prevent two or more users perform changes to the state at the same time.

When you call terraform plan, or terraform apply it locks the access to the state using the Lock ID in the dynamo table and then uses the terraform.state file to apply the changes to your infrastructure. When the changes are done, the terraform.state file is updated and the table is unlocked to allow new operations.

Create S3 Bucket

The code to create the S3 bucket is the following:

provider "aws" {
  region = "us-east-1"
  version = "~>2.59"

resource "aws_s3_bucket" "enterprise_backend_state" {
  bucket = "my-backend-bucket"

  lifecycle {
    prevent_destroy = true

  versioning {
    enabled = true

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"

Create the Dynamo Table

The code to create the dynamo table is the following:

resource "aws_dynamodb_table" "enterprise_backend_state" {
  hash_key = "LockID"
  name = "backend-lock-table"
  billing_mode = "PAY_PER_REQUEST"
  attribute {
    name = "LockID"
    type = "S"

Once you have an s3 bucket and the dynamo table you're ready to tell Terraform to store the state in s3 bucket from now on:

terraform {
  backend "s3" {
    bucket         = "my-backend-bucket"
    key            = "dev/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "backend-lock-table"
    encrypt        = true

That's it. You can do terraform init to execute the configuration. You'll notice Terraform will no continue storing the state on your disk. You´re ready to start collaborating with your team on the same infrastructure.