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.