OpenTofu → Terraform
Move configuration source and language, state, resource addresses, and provider ids, providers, resources, and schema versions, modules, components, and reusable libraries, backends, locking, encryption, and history, secrets, variables, configuration, and environments, imports, moves, aliases, and replacements, plans, previews, policy, and approvals from OpenTofu to Terraform with a reversible cutover, explicit exception ledger, and evidence-backed verification.
Should you make this move?
Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.
OpenTofu
- Open governance and strong Terraform compatibility provide a familiar declarative infrastructure workflow
- Declarative infrastructure makes environments reviewable, repeatable, and automatable
- Provider compatibility, state transitions, ecosystem divergence, and enterprise tooling still require evaluation
- State identity, provider behavior, secrets, and plans must remain aligned to avoid destructive changes
Terraform
- A vast provider and module ecosystem makes declarative multi-cloud infrastructure broadly understood
- Declarative infrastructure makes environments reviewable, repeatable, and automatable
- State safety, provider upgrades, licensing changes, and complex HCL systems demand careful governance
- State identity, provider behavior, secrets, and plans must remain aligned to avoid destructive changes
Terraform: A vast provider and module ecosystem makes declarative multi-cloud infrastructure broadly understood. This removes a major source-side concern: Provider compatibility, state transitions, ecosystem divergence, and enterprise tooling still require evaluation.
What you lose: Open governance and strong Terraform compatibility provide a familiar declarative infrastructure workflow. What you inherit: State safety, provider upgrades, licensing changes, and complex HCL systems demand careful governance.
Jump to a section
Know the shape of the move.
This timeline assumes
- Up to 200 stacks, 20,000 managed resources, 500 modules, and 100 deployment pipelines
- Administrators control both OpenTofu and Terraform, including billing, identity, APIs, integrations, and export permissions.
- OpenTofu remains intact and recoverable until Terraform completes one representative operating cycle.
- A production-shaped pilot includes every object type, access class, edge case, and failure path.
- The migration team preserves stable source identifiers and records durable evidence for every blocking check.
What survives the move.
“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.
| Item | Outcome | Impact | What happens | Mitigation |
|---|---|---|---|---|
| Configuration source and language | partial | critical | HCL compatibility, general-purpose language semantics, generated code, and project layout require review. A successful bulk job therefore does not prove semantic parity between OpenTofu and Terraform. | Map configuration source and language explicitly, pilot every feature class, and reconcile accepted, changed, rejected, and excluded items. |
| State, resource addresses, and provider IDs | partial | critical | State formats, addresses, lineage, serials, URNs, aliases, and provider identifiers must remain aligned. A successful bulk job therefore does not prove semantic parity between OpenTofu and Terraform. | Map state, resource addresses, and provider ids explicitly, pilot every feature class, and reconcile accepted, changed, rejected, and excluded items. |
| Providers, resources, and schema versions | partial | critical | Provider packages, forks, versions, defaults, unsupported resources, and upgrade behavior differ. A successful bulk job therefore does not prove semantic parity between OpenTofu and Terraform. | Map providers, resources, and schema versions explicitly, pilot every feature class, and reconcile accepted, changed, rejected, and excluded items. |
| Modules, components, and reusable libraries | partial | high | Module sources, component abstractions, inputs, outputs, and version constraints require conversion. A successful bulk job therefore does not prove semantic parity between OpenTofu and Terraform. | Map modules, components, and reusable libraries explicitly, pilot every feature class, and reconcile accepted, changed, rejected, and excluded items. |
| Backends, locking, encryption, and history | manual | critical | Remote state services, locks, encryption, retention, and recovery use different controls. A successful bulk job therefore does not prove semantic parity between OpenTofu and Terraform. | Inventory and rebuild backends, locking, encryption, and history, then test normal, edge, failure, and rollback behavior. |
| Secrets, variables, configuration, and environments | manual | critical | Secret stores, sensitivity, environment inheritance, stacks, and variable precedence differ. A successful bulk job therefore does not prove semantic parity between OpenTofu and Terraform. | Inventory and rebuild secrets, variables, configuration, and environments, then test normal, edge, failure, and rollback behavior. |
| Imports, moves, aliases, and replacements | manual | critical | Resource adoption and refactoring operations can silently schedule destructive replacement. A successful bulk job therefore does not prove semantic parity between OpenTofu and Terraform. | Inventory and rebuild imports, moves, aliases, and replacements, then test normal, edge, failure, and rollback behavior. |
| Plans, previews, policy, and approvals | manual | critical | Diff rendering, saved plans, policy engines, approvals, and drift controls need reconstruction. A successful bulk job therefore does not prove semantic parity between OpenTofu and Terraform. | Inventory and rebuild plans, previews, policy, and approvals, then test normal, edge, failure, and rollback behavior. |
| CI/CD, runners, identities, and cloud access | manual | critical | Workflow commands, plugins, credentials, OIDC, caches, and concurrent applies change. A successful bulk job therefore does not prove semantic parity between OpenTofu and Terraform. | Inventory and rebuild ci/cd, runners, identities, and cloud access, then test normal, edge, failure, and rollback behavior. |
| Run history, drift evidence, and rollback | lost | high | Historical plans, logs, policy results, and state versions do not all transfer as native history. A successful bulk job therefore does not prove semantic parity between OpenTofu and Terraform. | Archive run history, drift evidence, and rollback as dated source evidence and define the new destination baseline. |
Where each thing goes.
| Source | Destination | Method | Notes |
|---|---|---|---|
| OpenTofu: Configuration source and language | Terraform: approved configuration source and language representation | transform | Preserve source IDs, ownership, timestamps, access intent, and an explicit exception status for configuration source and language. |
| OpenTofu: State, resource addresses, and provider IDs | Terraform: approved state, resource addresses, and provider ids representation | transform | Preserve source IDs, ownership, timestamps, access intent, and an explicit exception status for state, resource addresses, and provider ids. |
| OpenTofu: Providers, resources, and schema versions | Terraform: approved providers, resources, and schema versions representation | transform | Preserve source IDs, ownership, timestamps, access intent, and an explicit exception status for providers, resources, and schema versions. |
| OpenTofu: Modules, components, and reusable libraries | Terraform: approved modules, components, and reusable libraries representation | transform | Preserve source IDs, ownership, timestamps, access intent, and an explicit exception status for modules, components, and reusable libraries. |
| OpenTofu: Backends, locking, encryption, and history | Terraform: approved backends, locking, encryption, and history representation | manual | Preserve source IDs, ownership, timestamps, access intent, and an explicit exception status for backends, locking, encryption, and history. |
| OpenTofu: Secrets, variables, configuration, and environments | Terraform: approved secrets, variables, configuration, and environments representation | manual | Preserve source IDs, ownership, timestamps, access intent, and an explicit exception status for secrets, variables, configuration, and environments. |
| OpenTofu: Imports, moves, aliases, and replacements | Terraform: approved imports, moves, aliases, and replacements representation | manual | Preserve source IDs, ownership, timestamps, access intent, and an explicit exception status for imports, moves, aliases, and replacements. |
| OpenTofu: Plans, previews, policy, and approvals | Terraform: approved plans, previews, policy, and approvals representation | manual | Preserve source IDs, ownership, timestamps, access intent, and an explicit exception status for plans, previews, policy, and approvals. |
| OpenTofu: CI/CD, runners, identities, and cloud access | Terraform: approved ci/cd, runners, identities, and cloud access representation | manual | Preserve source IDs, ownership, timestamps, access intent, and an explicit exception status for ci/cd, runners, identities, and cloud access. |
Make the move recoverable.
Create the source-of-truth backup
Preserve OpenTofu data, configuration, access, and operating evidence before any destination write.
- Export every available OpenTofu object and binary in scope, including configuration source and language, state, resource addresses, and provider ids, providers, resources, and schema versions, modules, components, and reusable libraries.
- Capture configuration and runtime dependencies for backends, locking, encryption, and history, secrets, variables, configuration, and environments, imports, moves, aliases, and replacements, plans, previews, policy, and approvals.
- Record counts, sizes, owners, timestamps, access classes, financial totals where applicable, and known exceptions.
- Hash immutable exports, record tool versions and commands, and transform working copies only.
Proof to capture: A signed manifest accounts for every scoped record class, configuration object, binary, count, total, exception, and hash.
Identity, schema, and disposition registry
Preserve stable identity and make every mapping or exclusion reviewable.
- Inventory source types, identifiers, owners, states, and access.
- Define one approved destination representation or explicit archive decision.
- Reject unmapped critical items and produce an exception ledger.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
Dependency-ordered migration package
Load prerequisite identities and configuration before dependent records and runtime actions.
- Normalize encoding, timestamps, identifiers, nulls, and destination limits.
- Run a representative pilot and retain request, response, and rejection evidence.
- Reconcile the final delta before enabling destination production writers.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
The things most likely to hurt.
These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.
A completed migration hides missing or altered configuration source and language
Headline counts look plausible while semantic, access, or relationship checks fail.
- Consequence
- The destination becomes authoritative with incomplete or misleading business data.
- Mitigation
- Reconcile by type, state, owner, access class, and representative record rather than total count alone.
Stop if: Any critical item lacks a verified destination, approved transformation, explicit exclusion, or recoverable archive.
OpenTofu and Terraform both perform production actions
Users, schedules, webhooks, integrations, or traffic continue changing both systems.
- Consequence
- State diverges or customers receive duplicate, contradictory, or unsafe actions.
- Mitigation
- Freeze source writers and transfer one production owner at a time with an approved rollback.
Stop if: An unapproved source writer or destination duplicate action appears after the freeze.
Destination access or security is broader than approved
A representative restricted user can read, change, export, or trigger an unauthorized item.
- Consequence
- Confidential, regulated, financial, or security-sensitive data is exposed or changed.
- Mitigation
- Apply least privilege before bulk loading and test every access class using ordinary identities.
Stop if: Any unauthorized read, write, export, administrative action, or secret access succeeds.
Do the work in this order.
- Days 1–4 · inventory
Inventory and decisions
8–16 hours active2–4 days elapsedOwner, legal, security, and finance review waiting- Inventory OpenTofu data, configuration, identities, integrations, limits, and billing.
- Approve scope, owners, mappings, exclusions, acceptance thresholds, and rollback authority.
Depends on: OpenTofu and Terraform administrator access
Stop / go checkpointExport?
Go when: Every critical item and production action has an owner and disposition.
Stop when: Authority, retention, billing, access, or system ownership is unclear.
- Days 3–8 · backup
Backup and reconcile
8–20 hours active2–5 days elapsedProvider export processing waiting- Create immutable data, configuration, binary, and audit exports.
- Reconcile source counts, totals, sizes, access classes, and hashes.
Depends on: Approved inventory and retention location
Stop / go checkpointTransform?
Go when: The signed source manifest and exports agree.
Stop when: Any critical dataset, binary, configuration, or recovery path is absent.
- Days 6–20 · pilot
Map, transform, and pilot
25–70 hours active5–12 days elapsedDestination processing and owner review waiting- Configure Terraform and transform a production-shaped pilot.
- Test normal records, every feature class, edge cases, permissions, failures, and rollback.
Depends on: Verified source backup and approved mapping registry
Stop / go checkpointScale?
Go when: Every pilot mapping and blocking verification check passes.
Stop when: Any critical invariant, access boundary, or production action lacks a safe destination.
- Days 18–35 · cutover
Bulk load, final delta, and switch
20–55 hours active2–8 days elapsedImports, propagation, indexing, or synchronization waiting- Freeze production writes and automated actions in OpenTofu.
- Apply and reconcile the final delta, switch ownership to Terraform, and run all blocking checks.
Depends on: Passed pilot, stakeholder go decision, and rehearsed rollback
Stop / go checkpointOpen production?
Go when: Terraform is the sole production owner and every critical exception is resolved.
Stop when: A source writer remains active, a blocking check fails, or rollback is unavailable.
- Days 25–45 · observe
Observe and close
9–19 hours active7–14 days elapsedRepresentative operating-cycle evidence waiting- Monitor correctness, access, failures, latency, delivery, cost, and user outcomes.
- Sign the verification report and close rollback only after stable evidence.
Depends on: Verified cutover
Stop / go checkpointClose rollback?
Go when: No trigger occurs during the approved observation period.
Stop when: Data, access, delivery, routing, cost, or business results regress.
Cut over with a way back.
Cutover
Make Terraform the only production system without losing the final OpenTofu delta.
- Freeze user, integration, schedule, and API writes in OpenTofu.
- Capture and reconcile the final source delta against the last verified checkpoint.
- Apply the approved delta and configuration changes to Terraform.
- Switch traffic, domains, integrations, credentials, automation, and user entry points in dependency order.
- Run every blocking verification check and keep the source intact.
Proof to capture: Terraform alone owns production, totals reconcile, exceptions are signed, and every blocking check has durable evidence.
Rollback
Return production ownership to OpenTofu without losing destination-era changes.
- Stop new user, integration, schedule, and API writes in Terraform.
- Restore prior OpenTofu traffic, domains, credentials, automation, and integration ownership.
- Export and classify the Terraform post-cutover delta.
- Apply safe destination-era changes back to OpenTofu without duplicating actions.
- Run the same blocking checks against the restored source.
Proof to capture: OpenTofu again owns production with current data and no duplicate destination action.
- Unexplained critical count, value, relationship, or checksum variance
- Missing, corrupted, or exposed critical data
- Duplicate production action or unresolved split-brain state
- Failed access, security, delivery, routing, performance, or integration check
- A critical feature has no safe destination replacement or rollback path
Prove the migration worked.
Every blocking check must pass. Capture the evidence before cleanup begins.
| Pass | ID | Check | Method | Expected result | Evidence |
|---|---|---|---|---|---|
V-01Blocking | Configuration source and language reconciliation | Compare source inventory, transformed output, destination results, and a stratified sample for configuration source and language. | Every in-scope item is present, intentionally transformed, explicitly excluded, or retained in the signed source archive. | Configuration source and language ledger with counts, exceptions, sample IDs, and owner sign-off. | |
V-02Blocking | State, resource addresses, and provider IDs reconciliation | Compare source inventory, transformed output, destination results, and a stratified sample for state, resource addresses, and provider ids. | Every in-scope item is present, intentionally transformed, explicitly excluded, or retained in the signed source archive. | State, resource addresses, and provider IDs ledger with counts, exceptions, sample IDs, and owner sign-off. | |
V-03Blocking | Providers, resources, and schema versions reconciliation | Compare source inventory, transformed output, destination results, and a stratified sample for providers, resources, and schema versions. | Every in-scope item is present, intentionally transformed, explicitly excluded, or retained in the signed source archive. | Providers, resources, and schema versions ledger with counts, exceptions, sample IDs, and owner sign-off. | |
V-04Blocking | Modules, components, and reusable libraries reconciliation | Compare source inventory, transformed output, destination results, and a stratified sample for modules, components, and reusable libraries. | Every in-scope item is present, intentionally transformed, explicitly excluded, or retained in the signed source archive. | Modules, components, and reusable libraries ledger with counts, exceptions, sample IDs, and owner sign-off. | |
V-05Blocking | Backends, locking, encryption, and history reconciliation | Compare source inventory, transformed output, destination results, and a stratified sample for backends, locking, encryption, and history. | Every in-scope item is present, intentionally transformed, explicitly excluded, or retained in the signed source archive. | Backends, locking, encryption, and history ledger with counts, exceptions, sample IDs, and owner sign-off. | |
V-06Blocking | Secrets, variables, configuration, and environments reconciliation | Compare source inventory, transformed output, destination results, and a stratified sample for secrets, variables, configuration, and environments. | Every in-scope item is present, intentionally transformed, explicitly excluded, or retained in the signed source archive. | Secrets, variables, configuration, and environments ledger with counts, exceptions, sample IDs, and owner sign-off. | |
V-07Blocking | Imports, moves, aliases, and replacements reconciliation | Compare source inventory, transformed output, destination results, and a stratified sample for imports, moves, aliases, and replacements. | Every in-scope item is present, intentionally transformed, explicitly excluded, or retained in the signed source archive. | Imports, moves, aliases, and replacements ledger with counts, exceptions, sample IDs, and owner sign-off. | |
V-08Blocking | Plans, previews, policy, and approvals reconciliation | Compare source inventory, transformed output, destination results, and a stratified sample for plans, previews, policy, and approvals. | Every in-scope item is present, intentionally transformed, explicitly excluded, or retained in the signed source archive. | Plans, previews, policy, and approvals ledger with counts, exceptions, sample IDs, and owner sign-off. |
Remove the scaffolding safely.
Safe after: One complete operating cycle, at least seven stable days, and owner sign-off on every blocking check and exception.
- Create final OpenTofu exports and archive verification, access, financial, and rollback evidence.
- Revoke temporary credentials, API keys, webhooks, elevated roles, and migration network access.
- Remove obsolete jobs, embeds, domains, integrations, collectors, routes, and DNS records.
- Keep the source intact and read-only through the approved legal and operational retention window.
- Cancel paid plans only after billing, legal, security, evidence, and recovery review.
- Schedule the next Terraform backup, restore test, access review, and migration-playbook review.
Verify against the primary material.
Platform behavior changes. Check these sources and the review dates above before executing a production migration.
- OpenTofu: official portability and migration documentationAccessed 2026-07-20
- Terraform: official portability and migration documentationAccessed 2026-07-20