Open-Source Wikis

/

Terraform

/

Reference

/

Data models

hashicorp/terraform

Data models

The on-disk artifacts Terraform produces and consumes. All formats are versioned; backward compatibility is a design constraint.

State file (terraform.tfstate)

Versioned JSON, currently version 4. Defined by internal/states/statefile/.

Top-level shape:

{
  "version": 4,
  "terraform_version": "1.16.0",
  "serial": 13,
  "lineage": "abcdef12-3456-7890-abcd-ef1234567890",
  "outputs": {
    "instance_ip": {
      "value": "10.0.0.1",
      "type": "string",
      "sensitive": false,
    },
  },
  "resources": [
    {
      "module": "module.web",
      "mode": "managed",
      "type": "aws_instance",
      "name": "web",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            /* schema-shaped JSON */
          },
          "sensitive_attributes": [],
          "private": "<base64>",
          "dependencies": ["aws_security_group.web"],
          "create_before_destroy": false,
          "identity_schema_version": 0,
          "identity": {
            /* identity-schema-shaped JSON */
          },
        },
      ],
    },
  ],
  "check_results": [
    /* ... */
  ],
}

Field notes:

  • serial increments on every write. Remote state managers use it to detect concurrent writes.
  • lineage is a UUID generated at first write. Mismatch indicates "different state on the other end" and aborts writes.
  • mode is managed for resource blocks, data for data blocks, ephemeral for ephemeral resources, list for the new list-resource type.
  • provider is the full addrs.AbsProviderConfig string form.
  • attributes follows the shape of the provider's resource schema at the version recorded in schema_version. The provider's UpgradeResourceState is called to migrate when the schema version is older than the provider's current version.
  • sensitive_attributes is a list of attribute paths (e.g. [".password"]) marked sensitive — re-applied as cty marks at load time.
  • identity and identity_schema_version are 1.16+ — provider-assigned stable identifiers.
  • dependencies is the list of resource addresses this instance refers to. The walker uses it for destroy-time ordering when the configuration is no longer present.

Older state file versions live in version1.go, version2.go, version3.go. The upgrade.go machinery chains them: a v1 file is upgraded to v2, then v3, then v4, in memory. Writes only emit v4.

Plan file (<output> from terraform plan -out=...)

A zip archive defined by internal/plans/planfile/. Contents:

Path inside zip Contents
tfplan Protobuf-encoded plan (schema in internal/plans/planproto/).
tfstate Prior state at plan time, in the v4 format.
dependency-lock.hcl Snapshot of .terraform.lock.hcl so apply uses the same provider versions.
Multiple files under terraform-config/ Tar-archived configuration.

The plan file is self-contained: terraform apply <planfile> works without re-reading the user's .tf files. This is a deliberate property — planfiles are often produced on one machine (CI) and applied on another (a deployment runner).

The protobuf schema is reasonably stable but not as locked-down as the state schema. Plans are short-lived (typically minutes to hours), so newer Terraform versions don't always read older plans. Errors in this case point users to re-running terraform plan.

Dependency lock file (.terraform.lock.hcl)

HCL-formatted, defined by internal/depsfile/. One block per provider:

provider "registry.terraform.io/hashicorp/aws" {
  version     = "5.42.0"
  constraints = "~> 5.0"
  hashes = [
    "h1:abc...",
    "zh:def...",
    "256colon:1234..."
  ]
}

Fields:

  • version — the version terraform init selected.
  • constraints — the version constraints from required_providers.
  • hashes — one or more package hashes used for verification on subsequent runs.

Hash formats:

  • h1: — base64 of SHA256 of the package contents (canonical).
  • zh: — SHA256 of the entire zip archive (used by some sources).
  • 256colon: — colon-separated hex SHA256 (used by some mirrors).

A given provider can have multiple hashes — typically one per platform — so the lock file can be portable across operating systems. The terraform providers lock subcommand adds platform-specific hashes.

JSON output formats (the -json outputs)

These are public APIs. Their schemas are defined in:

Each package defines a top-level MarshalForFoo(...) function plus a stable struct schema. The format_version field in each output is bumped when the structure changes incompatibly; consumers should branch on it.

Module manifest (.terraform/modules/modules.json)

Format owned by internal/modsdir/. One entry per installed module instance:

{
  "Modules": [
    {
      "Key": "",
      "Source": "",
      "Dir": ".",
    },
    {
      "Key": "web",
      "Source": "./modules/web",
      "Dir": "modules/web",
    },
    {
      "Key": "web.network",
      "Source": "../shared/network",
      "Dir": ".terraform/modules/web.network",
    },
  ],
}

Used by internal/configs/configload.Loader to translate from module.<name>.<sub> references to on-disk paths without re-running module installation.

Workspace marker (.terraform/environment)

A plain text file containing the selected workspace name. Used by the local backend; remote backends manage their own workspace state internally.

CLI configuration (~/.terraformrc)

See configuration. Format owned by internal/command/cliconfig/.

What's not a stable format

  • internal/stacks/tfstackdata1/ — internal protobuf for stack plans/states. The README explicitly states this is internal; clients must use the rpcapi.
  • The crash.log format produced by internal/logging/panic.go — Go's default panic dump, not a stable schema.
  • Internal log line formats ([TRACE] ...) — for human consumption only.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Data models – Terraform wiki | Factory