# How to Create a Terraform Archive File for Deployment: A Complete Guide

> Effectively create a terraform archive file for deployment using terraform plan -out=plan.zip. This guide details bundling plan, state, and config into a single zip archive for streamlined deployments.

- Repository: [HashiCorp/terraform](https://github.com/hashicorp/terraform)
- Tags: how-to-guide
- Published: 2026-02-16

---

**The most effective method for creating a terraform archive file is using `terraform plan -out=plan.zip`, which internally invokes the `planfile.Create` function to bundle the plan, state files, configuration snapshot, and lock file into a single zip archive.**

A terraform archive file serves as the deployment artifact in Terraform's remote execution workflow, encapsulating everything needed to apply infrastructure changes without access to the original configuration source. This article examines the implementation in the `hashicorp/terraform` repository to explain how these archives are structured, generated, and used in production deployment pipelines.

## What Is a Terraform Archive File?

A terraform archive file is a **zip archive** that contains the complete context required to execute a plan remotely. According to the source code in [`internal/plans/planfile/writer.go`](https://github.com/hashicorp/terraform/blob/main/internal/plans/planfile/writer.go), the archive bundles five critical components:

- **Serialized plan** (`tfplan`): The binary plan output containing the proposed resource changes
- **Current state** (`tfstate`): The latest Terraform state file after refresh operations
- **Previous state** (`tfstate-prev`): The state file from before the last apply operation
- **Configuration snapshot**: A complete copy of the `.terraform` module tree and configuration files stored under a virtual `tfconfig/` directory
- **Dependency lock file** (`dependency-locks.hcl`): The `.terraform.lock.hcl` content when present, ensuring consistent provider versions

## How Terraform Creates Archive Files Internally

The archive creation process centers on the `planfile.Create` function located in [`internal/plans/planfile/writer.go`](https://github.com/hashicorp/terraform/blob/main/internal/plans/planfile/writer.go). This function is invoked by the CLI when executing `terraform plan -out=<filename>` and by remote backends when preparing deployment artifacts.

### The Archive Creation Process in writer.go

The `planfile.Create` function executes a precise sequence of operations to construct the zip archive:

1. **Open output file** (line 55): Uses `os.Create` to open or truncate the target archive file
2. **Initialize zip writer** (line 61): Wraps the file handle with `zip.NewWriter` to begin zip entry construction
3. **Write plan binary** (lines 66-74): Serializes the `plans.Plan` object into a `tfplan` entry using `Deflate` compression
4. **Embed current state** (lines 80-92): Calls `statefile.Write` to store the refreshed state as `tfstate`
5. **Embed previous state** (lines 96-108): Stores the prior run state as `tfstate-prev` using the same method
6. **Snapshot configuration** (lines 112-119): Walks the configuration directory and stores each file under the virtual `tfconfig/` path
7. **Include lock file** (lines 120-138): If `DependencyLocks` is provided, writes the content as `dependency-locks.hcl`
8. **Finalize archive** (line 141): Closes the zip writer to flush all entries and complete the archive

### Backend Integration

The archive creation is triggered from backend implementations after a successful plan operation. In [`internal/backend/local/backend_plan.go`](https://github.com/hashicorp/terraform/blob/main/internal/backend/local/backend_plan.go) at line 187, the local backend invokes `planfile.Create` to persist the plan and its associated context to disk:

```go
// From internal/backend/local/backend_plan.go
if err := planfile.Create(planOutPath, planfile.CreateArgs{
    ConfigSnapshot:       configSnapshot,
    PreviousRunStateFile: previousStateFile,
    StateFile:            stateFile,
    Plan:                 plan,
    DependencyLocks:      dependencyLocks,
}); err != nil {
    // Handle error
}

```

## Creating a Terraform Archive File: CLI Method

For standard deployment workflows, use the Terraform CLI to generate the archive automatically. This method ensures all components are correctly serialized and compressed according to the internal specification.

```bash

# Create a plan and save it as a zip archive

terraform plan -out=deployment-plan.zip

# Apply the archived plan on a remote executor or different machine

terraform apply deployment-plan.zip

```

When you specify the `-out` flag, Terraform executes the full plan workflow, then calls `planfile.Create` to bundle the resulting plan with the current state, configuration snapshot, and lock file into the specified zip archive.

## Creating a Terraform Archive File Programmatically

For custom tooling or CI/CD pipelines that need to generate archives without invoking the CLI directly, use the internal `planfile` package. This approach requires importing the Terraform internal packages and constructing the `CreateArgs` struct with properly initialized objects.

```go
package main

import (
	"log"

	"github.com/hashicorp/terraform/internal/configs/configload"
	"github.com/hashicorp/terraform/internal/depsfile"
	"github.com/hashicorp/terraform/internal/plans"
	"github.com/hashicorp/terraform/internal/plans/planfile"
	"github.com/hashicorp/terraform/internal/states/statefile"
)

func main() {
	// These objects would be populated from your Terraform workflow:
	var cfgSnap *configload.Snapshot   // Configuration snapshot
	var prevState *statefile.File      // Previous run state
	var curState *statefile.File       // Current refreshed state
	var tfPlan *plans.Plan             // The computed plan
	var locks *depsfile.Locks          // Dependency locks (optional)

	args := planfile.CreateArgs{
		ConfigSnapshot:       cfgSnap,
		PreviousRunStateFile: prevState,
		StateFile:            curState,
		Plan:                 tfPlan,
		DependencyLocks:      locks,
	}

	// Create the archive at the specified path
	if err := planfile.Create("deployment-plan.zip", args); err != nil {
		log.Fatalf("failed to create terraform archive file: %v", err)
	}
}

```

**Important considerations for programmatic use:**

- Import paths use `github.com/hashicorp/terraform/internal/...` which are internal packages subject to change between releases
- The `ConfigSnapshot` must contain the complete module tree and configuration files
- State files must be properly formatted `*statefile.File` objects, not raw JSON
- Dependency locks ensure provider version consistency across execution environments

## Key Source Files for Terraform Archive Creation

Understanding the implementation requires examining these specific files in the `hashicorp/terraform` repository:

| File | Purpose |
|------|---------|
| [`internal/plans/planfile/writer.go`](https://github.com/hashicorp/terraform/blob/main/internal/plans/planfile/writer.go) | Core implementation of `planfile.Create` that constructs the zip archive with all components |
| [`internal/backend/local/backend_plan.go`](https://github.com/hashicorp/terraform/blob/main/internal/backend/local/backend_plan.go) | Local backend that invokes `planfile.Create` at line 187 after plan execution |
| [`internal/plans/planfile/reader.go`](https://github.com/hashicorp/terraform/blob/main/internal/plans/planfile/reader.go) | Counterpart that reads and validates the archive on the remote execution side |
| [`internal/terraform/context_test.go`](https://github.com/hashicorp/terraform/blob/main/internal/terraform/context_test.go) | Test suite validating archive creation and extraction workflows |
| [`internal/command/command_test.go`](https://github.com/hashicorp/terraform/blob/main/internal/command/command_test.go) | Integration tests ensuring the CLI properly generates archive files |

## Summary

- A **terraform archive file** is a zip bundle containing the plan binary, current and previous state files, configuration snapshot, and dependency locks required for remote execution.
- The most effective creation method is the CLI command `terraform plan -out=plan.zip`, which internally calls `planfile.Create` in [`internal/plans/planfile/writer.go`](https://github.com/hashicorp/terraform/blob/main/internal/plans/planfile/writer.go).
- For programmatic generation, import the internal `planfile` package and populate `CreateArgs` with configuration snapshots, state files, and plan objects.
- The archive format uses standard zip compression with specific entry names (`tfplan`, `tfstate`, `tfconfig/`, etc.) that the reader implementation expects in [`internal/plans/planfile/reader.go`](https://github.com/hashicorp/terraform/blob/main/internal/plans/planfile/reader.go).

## Frequently Asked Questions

### What exactly is inside a terraform archive file?

A terraform archive file contains five essential components: the serialized plan binary (`tfplan`), the current state file (`tfstate`), the previous state file (`tfstate-prev`), a complete snapshot of your configuration stored under `tfconfig/`, and optionally the dependency lock file (`dependency-locks.hcl`). These components are bundled by the `planfile.Create` function in [`internal/plans/planfile/writer.go`](https://github.com/hashicorp/terraform/blob/main/internal/plans/planfile/writer.go) to ensure the remote executor has everything needed to apply the plan without access to your source repository.

### Can I create a terraform archive file without using the CLI?

Yes, you can create a terraform archive file programmatically by importing the internal `github.com/hashicorp/terraform/internal/plans/planfile` package and calling `planfile.Create` with a populated `CreateArgs` struct. This approach requires constructing configuration snapshots, state file objects, and plan structures manually, which is typically only done when building custom CI/CD tooling. Note that internal packages are subject to breaking changes between Terraform releases.

### How does Terraform Cloud use the archive file?

When you run `terraform plan -out=plan.zip` and configure a remote backend like Terraform Cloud, the CLI automatically uploads the archive file to the remote executor. The server-side implementation uses [`internal/plans/planfile/reader.go`](https://github.com/hashicorp/terraform/blob/main/internal/plans/planfile/reader.go) to extract the plan, state, and configuration snapshot from the zip entries. This allows the remote agent to apply the plan in a secure, isolated environment without requiring access to your local configuration files or state storage.

### What compression method does Terraform use for archive files?

Terraform uses standard **Deflate** compression for the zip archive entries, specifically when writing the `tfplan` binary in [`internal/plans/planfile/writer.go`](https://github.com/hashicorp/terraform/blob/main/internal/plans/planfile/writer.go) (lines 66-74). The implementation uses Go's standard `archive/zip` package with `zip.Deflate` as the compression method. State files and configuration snapshots are also stored within the same zip container, though the specific compression settings may vary by entry type based on the writer implementation.