Study guide
11.1 The Local Backend
HashiCorp Certified: Terraform Associate 004
Track your progress as you read
Finished sections get a check mark.
1 Introduction & Exam Overview
1.1 Current Exam Facts 1.2 Format, Delivery, Retakes, and Recertification 1.3 004 Changes, Terraform 1.12, and Study Plan
2 Infrastructure as Code with Terraform
2.1 What Infrastructure as Code Is 2.2 Advantages of IaC Patterns 2.3 Multi-Cloud, Hybrid, and Service-Agnostic Workflows
3 Terraform Fundamentals: Providers & State
3.1 Install and Version Terraform Providers 3.2 How Terraform Uses Providers 3.3 Configuration with Multiple Providers 3.4 How Terraform Uses and Manages State
4 Core Terraform Workflow: Init & Validate
4.1 The Terraform Write–Plan–Apply Workflow 4.2 Initialize a Working Directory 4.3 Validate a Configuration
5 Plan, Apply, Destroy, and Formatting
5.1 Generate and Review an Execution Plan 5.2 Apply Changes to Infrastructure 5.3 Destroy Terraform-Managed Infrastructure 5.4 Formatting and Style Adjustments
6 Resources, Data Sources, and References
6.1 Resource Blocks vs Data Blocks 6.2 Resource Attributes and Cross-Resource References 6.3 Resource Addressing and Interpolation Patterns
7 Variables, Outputs, and Complex Types
7.1 Input Variables, tfvars, and Precedence 7.2 Output Values 7.3 Complex Types: list, map, object, tuple, set
8 Dynamic Configuration and Dependencies
8.1 Expressions, count, for_each, and dynamic Blocks 8.2 Built-in Functions 8.3 Dependencies, depends_on, and Lifecycle Rules
9 Conditions, Secrets, and Sensitive Data
9.1 Custom Conditions: validation, precondition, postcondition, check 9.2 Sensitive Data Handling 9.3 Vault, Ephemeral Values, and Write-Only Arguments
10 Terraform Modules
10.1 How Terraform Sources Modules 10.2 Variable Scope within Modules 10.3 Using Modules in Configuration 10.4 Managing Module Versions
11 Terraform State Management
11.1 The Local Backend 11.2 State Locking 11.3 Remote State and the backend Block 11.4 Resource Drift and State Operations
12 Maintain Infrastructure with Terraform
12.1 Import Existing Infrastructure 12.2 Inspect State with the CLI 12.3 Verbose Logging and Diagnostics
13 HCP Terraform
13.1 Create Infrastructure with HCP Terraform 13.2 Collaboration and Governance Features 13.3 Workspaces and Projects 13.4 HCP Terraform Integrations
11.1 The Local Backend
Key Takeaways Explain This Topic AI
If you omit both a backend block and a cloud block, Terraform 1.12 uses the local backend and writes terraform.tfstate in the working directory
The local backend also writes terraform.tfstate.backup with the previous snapshot and locks with local system APIs, which does not protect two laptops
An explicit backend "local" block can set path and workspace_dir; omitting the block is the same default backend
Local state is fine for learning and a single engineer; HashiCorp recommends HCP Terraform or a remote backend for teams
Never commit terraform.tfstate; changing the backend requires terraform init again, usually with -migrate-state or -reconfigure
Last updated: August 2026
11.1 The Local Backend
Quick Answer: Omit backend and cloud and Terraform 1.12 uses the local backend. It writes terraform.tfstate (current snapshot) and terraform.tfstate.backup (previous snapshot) in the working directory, and it locks with local system APIs. That is enough for a tutorial on one laptop. It is not a team backend. Do not commit the state file. Changing the backend later requires terraform init again.
Objective 6a on Terraform Associate (004) asks you to describe the local backend. Chapter 3.4 already explained why state exists (bindings, metadata, cached attributes). This section is the default storage engine for those snapshots. Official references: Backend Type: local and State .
Default backend if you configure nothing
HashiCorp's backend overview is explicit: Terraform uses a backend called local by default. You do not have to write a backend block to get it. A root module that only has required_providers and resource blocks still has a backend — the local one.
The local backend is documented as Kind: Enhanced . That label means three things at once:
It stores state on the local filesystem.
It locks that state using system APIs.
It performs operations locally (plan and apply run on your machine, not on a remote runner).
Those three jobs are what a backend is. The local backend is not a special exception; it is the built-in implementation you get when you have not selected another store.
A cloud block (HCP Terraform / Terraform Enterprise) is an alternative to any backend block, including local. If the configuration has no cloud block and no backend block, the engine is still local. You cannot combine cloud and backend — that pairing is illegal HCL and is tested in 6c.
The two files on disk
HashiCorp's state page states the default filenames:
- terraform.tfstate — the current workspace snapshot, JSON text, next to your .tf files
- terraform.tfstate.backup — the previous snapshot, rewritten when Terraform writes a new current snapshot
File What it is When it appears Commit?
terraform.tfstate Current bindings, metadata, cached attributes After the first successful write (usually the first apply) No
terraform.tfstate.backup Previous local snapshot After the second successful write No
.terraform/terraform.tfstate Backend configuration metadata for this working directory, not the infrastructure snapshot After terraform init No
.terraform.lock.hcl Pinned provider versions and checksums After init Yes
Do not confuse .terraform/terraform.tfstate with terraform.tfstate . The file under .terraform/ records which backend this directory is using . The file in the working directory is the infrastructure state when the backend is local. After you migrate to S3 or HCP Terraform, the real snapshot lives remotely; the leftover local terraform.tfstate is no longer the source of truth.
- You can name the snapshot something else with an explicit block: terraform {
- backend "local" {
- path = "relative/path/to/terraform.tfstate"
- workspace_dir = "relative/path/to/workspaces"
- }
- }
Official arguments:
path (optional) — path to the tfstate file. Default is terraform.tfstate relative to the root module.
workspace_dir (optional) — directory that holds non-default CLI workspaces.
With the defaults, the default workspace uses terraform.tfstate in the working directory. Other CLI workspaces ( terraform workspace new staging ) use a per-workspace file under terraform.tfstate.d/<name>/ . Setting workspace_dir relocates that non-default tree. Switching CLI workspaces does not change your .tf files; it changes which local snapshot the next plan reads.
Local locking is real, and it is limited
The local backend locks with system APIs (file locks on that machine and that filesystem). Two terraform apply processes in the same directory on the same host will not both write. That is better than no lock at all.
It does not protect a team:
Ava's laptop and Ben's laptop each have their own terraform.tfstate . Local locks never see each other.
A copy of the file on a USB stick or in email is a second writer with no shared lock.
Network filesystems and some container mounts implement file locks poorly; HashiCorp does not present local locking as a collaboration feature.
terraform force-unlock is documented as unable to unlock a local state file from another process. If a local lock is stuck, it is a local-process problem, not a remote lock ID you can force from a teammate's machine.
Fine for learning, not for teams
HashiCorp's state page says storing state locally requires no extra configuration, but it limits collaboration and risks losing the workspace if the file is lost. The recommendation is HCP Terraform or a remote backend.
Use local state when:
You are learning the write → init → plan → apply loop on one machine.
The objects are disposable lab resources.
Nobody else will apply the same configuration.
Do not use local state when:
Two engineers can apply.
A CI runner and a laptop can apply.
Losing the laptop would lose the only copy of the bindings.
The snapshot contains production secrets (it usually does).
Avoid storing state in Git or any other store that lacks Terraform locking and access control. Local state is plaintext JSON. Providers persist attributes there, including values that sensitive = true only redacts from CLI display. .terraform/
- *.tfplan
- terraform.tfstate
- terraform.tfstate.backup
- terraform.tfstate.d/
- crash.log
- Changing the backend requires re-init
The moment you add backend "s3" (or cloud ) and save, the working directory is out of date. HashiCorp: when you change a backend's configuration you must run terraform init again before you can plan, apply, or run state commands.
On Terraform 1.12, re-init after a backend change requires either -migrate-state or -reconfigure :
- Flag What happens to existing local state
- terraform init -migrate-state Copies the existing snapshot into the new backend (may prompt per workspace)
- terraform init -force-copy Same copy, answers yes to prompts; implies -migrate-state
- terraform init -reconfigure Ignores the old backend configuration; does not copy state
Back up first. Official backend docs: before migrating, copy terraform.tfstate somewhere safe. After a successful migrate, the remote object is the live snapshot; delete or ignore the leftover local file so nobody applies it by accident.
Legacy CLI flags (do not treat as the modern design)
For local (or default-local) configurations only, older commands still accept -state , -state-out , and -backup . They override which filename Terraform reads and writes. HashiCorp preserves them for wrapper scripts that predated built-in remote state, and does not recommend them for new systems — including automation. They also disable the usual per-workspace filename selection if you set all three. They have no effect when a non-local backend is selected.
004 still expects you to recognize the names. The modern answer for shared state is a backend or cloud block, not a wrapper that copies files around -state .
Loading diagram...
Scenario: Jordan's first week
Jordan clones a tutorial, runs terraform init and terraform apply , and sees terraform.tfstate appear. That is 6a working as designed. On Friday Jordan emails the repo — including the state file — to a teammate. Both apply Monday morning. Each laptop locks its own copy, both writes succeed, and AWS now has objects that neither file fully describes. The exam answer is not "enable a better local lock." The exam answer is: local state is not a team backend; move to HCP Terraform or a remote backend and re-init.
- 004 traps for objective 6a
- No backend block still means the local backend, not "no backend."
terraform.tfstate is the snapshot; .terraform/terraform.tfstate is backend metadata.
Local locking exists and is still insufficient for two laptops.
Do not commit terraform.tfstate or terraform.tfstate.backup .
Switching backends is an init problem ( -migrate-state / -reconfigure ), not an apply problem.
-state / -state-out / -backup are legacy local-only flags, not the current team design.