Terraform manages infrastructure using a state file, which is stored by default as terraform.tfstate. This works fine when working alone, but if multiple people manage the infrastructure simultaneously, conflicts may arise.
To solve this issue, Terraform provides the backend block to configure where the state file is stored.
>> Read more:
- How To Use Terraform for Provisioning A Docker Container?
- How to Migrate Your AWS Workloads from EC2 to ECS?
What is Terraform Backend?
A Terraform backend defines how and where Terraform stores its state file (terraform.tfstate). This state file keeps track of the resources Terraform manages such as AWS instances, Azure services, or any infrastructure created using Terraform. Without it, Terraform won’t know what exists or what needs to be changed.
By default, the state is stored locally on your machine, but that becomes problematic when:
- Multiple team members are working on the same infrastructure.
- You want centralized control, locking, or history/versioning of infrastructure changes.
- You need the state file to persist beyond a single device.
To solve these issues, Terraform supports using remote backends like Amazon S3, Terraform Cloud, Azure Blob Storage, Google Cloud Storage, and more. With a Terraform remote backend, you are allowed:
- Shared access to the same state file
- State locking to prevent simultaneous updates
- Versioning and audit trails
- Better security and scalability
Terraform Backend Config
The backend block is placed at the beginning inside the terraform block. For example: Remote backend with Terraform Cloud:
terraform {
backend "remote" {
organization = "learning-journey"
workspaces {
name = "demo01"
}
}
}
Terraform provides multiple backend options, meaning different locations to store the state file, such as local, remote, s3, azurerm, etc. The default storage location is local.
Backend Types
As mentioned earlier, Terraform supports multiple backend types, but in this article, we will focus on local and s3.
Local
The local backend stores the state file on the user's machine.
Configuration:
terraform {
backend "local" {
path = "relative/path/to/terraform.tfstate"
}
}
path: Specifies where the state file is stored. By default, it is terraform.tfstate in the root module.
While easy to set up, the local backend is not recommended for teams. It doesn’t support locking, remote access, or version control, so conflicts may arise when multiple users manage infrastructure. Therefore, storing the state file in a shared location helps solve these conflicts, which is where the s3 backend comes in.
S3
With this Terraform S3 backend, the state file is stored in an S3 bucket. To ensure consistency, there are two ways to lock the state file:
- S3 state locking (
use_lockfile), available inTerraform 1.10 and later. - DynamoDB (
dynamodb_table), where the partition key isLockIDwith a data type ofstring.
Example: Create an S3 bucket and a DynamoDB table on AWS.
- Configuration:
terraform {
backend "s3" {
bucket = "mybucket"
key = "your-state.tfstate"
region = "us-east-1"
profile = "Your_Profile"
dynamodb_table = "states_tb"
}
}
- If using an AWS profile with S3 access permissions, no additional S3 permissions are required. Otherwise, you must configure permissions for reading and writing objects in S3:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::mybucket"
},
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": [
"arn:aws:s3:::mybucket/path/to/my/key",
"arn:aws:s3:::mybucket/path/to/my/key.tflock"
]
}
]
}
- If using DynamoDB for state locking, you must also set permissions for DynamoDB on AWS (if the profile lacks necessary permissions):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:DescribeTable",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:DeleteItem"
],
"Resource": "arn:aws:dynamodb:*:*:table/mytable"
}
]
}
Practices
This section demonstrates how to configure and verify Terraform remote state storage using Amazon S3, and how to enable state locking using either S3-native lockfile or DynamoDB.
Storing State in S3
- Modify
main.tfto include thebackendblock inside theterraformblock:
terraform {
backend "s3" {
bucket = "terraform-learning-demo01"
key = "terraform.tfstate"
region = "us-east-1"
profile = "saa"
}
...
}
- Firstly, create an S3 bucket on AWS with a name matching the bucket field in the backend block. Here, we use
terraform-learning-demo01. If not, we will encounter this issue:

- Reinitialize the workspace:
terraform init
This initializes the backend and connects Terraform to the specified S3 bucket.
Expected Output:
Initializing the backend...
Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing modules...
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v4.67.0
Terraform has been successfully initialized!
...
- Then, run
terraform planto check for changes, followed byterraform applyto deploy the infrastructure. - After execution, verify in the S3 bucket that the
terraform.state(key) file is stored interraform-learning-demo01(bucket).

- In the
.terraform/terraform.tfstatedirectory, you will find the information of backend configuration. This confirms that we have successfully configured state storage on S3.

State Locking
S3 State Locking
- To enable S3 state locking, add the
use_lockfileparameter (only available in Terraform 1.10+) to thebackendblock. Themain.tffile now looks like this:
terraform {
backend "s3" {
bucket = "terraform-learning-demo01"
key = "terraform.tfstate"
region = "us-east-1"
profile = "saa"
use_lockfile = true
}
...
}
...
- Modify a resource value (e.g., the subnet CIDR block) and run
terraform applysimultaneously. You will see an error in the console:

- A lock file
{key}.tflockappears in the S3 bucket, preventing simultaneous apply operations:

- Once the apply operation completes, the lock file is deleted, and the state file will be added in S3:

DynamoDB State Locking
- Create a DynamoDB table named
terraform-tfstatewithLockIDas the partition key of typestring.

- If not, this issue will appear:

- Configure DynamoDB in
main.tf:
terraform {
backend "s3" {
bucket = "terraform-learning-demo01"
key = "terraform.tfstate"
region = "us-east-1"
profile = "saa"
dynamodb_table = "terraform-tfstate"
}
}
- Running
terraform applysimultaneously will result in an error:

- The DynamoDB table contains a record with
LockIDformatted as{bucket}/{key}.

- Once apply excecuted, file
statewill be created inS3:

- Once the process completes, the lock record is deleted, but a
{bucket}/{key}-md5file is created:

>> Explore: Top 20 Infrastructure as Code (IaC) Tools For Businesses
Conclusion
- Terraform provides the
backendblock to define state file storage locations. - Multiple backend options are available:
local,remote,s3, etc. - The
s3backend supports state locking via S3 native (Terraform 1.10+) or DynamoDB:- When applying changes, a
.lockfile is created in S3 or DynamoDB. - Once the process completes, the lock file is removed, and the state file is updated in S3.
- When applying changes, a
>>> Follow and Contact Relia Software for more information!
- development
