December 10, 2025·6 min read·engineeringterraformcdktfmaintenancemigration

HashiCorp archives CDK for Terraform

CDKTF maintenance ends on December 10. HCL synthesis provides a starting point for migration, while resource identity and stack orchestration require separate attention.

Infrastructure described through a programming language still depends on the software that translates that program into Terraform configuration. That translation layer now has an explicit end of maintenance. HashiCorp archived the CDK for Terraform repository on December 10. Its notice says there will be no further fixes or compatibility updates, while the source remains available. Existing deployments are not automatically removed, but the software responsible for producing their configuration is now frozen.

I use Terraform as a daily driver because its language provides reusable abstractions over infrastructure APIs. CDKTF offered another way to produce those declarations, with the facilities of a general-purpose language. Its retirement makes the distinction between the authored program and the resulting Terraform configuration especially important for understanding what a migration preserves.

The maintenance decision concerns the translation layer

HashiCorp's notice attributes the decision to CDKTF not finding product-market fit at scale and says investment will focus on Terraform core and its broader ecosystem. It recommends standard Terraform and HCL for users without a tighter AWS CDK integration. The notice also encourages community forks, while making clear that HashiCorp will not provide subsequent compatibility work.

Those statements describe a maintenance boundary. Continuing to run an existing program is different from having a maintained tool that accommodates future changes in its dependencies. A frozen translator can remain useful with a known combination of inputs and tools. That does not establish compatibility with every subsequent provider schema or language-toolchain release.

The practical dependency is therefore broader than whether a package remains downloadable. Reproducing a synthesis result requires the application and the tooling that evaluates it. Availability of archived source preserves the possibility of investigation and independent maintenance, but it does not assign anyone the responsibility for performing that maintenance.

Synthesis produces configuration, not a replacement program

The CLI reference describes synth as generating Terraform configuration for an application. It normally places the result in cdktf.out, and warns that this output directory can be erased by later synthesis. The HCL option changes the output format from JSON to HCL.

cdktf synth --hcl

That command is useful because it exposes a configuration that Terraform can consume without requiring the original application to remain the editing interface. It does not translate the application's reusable classes and control flow into an equivalent source program in HCL. It emits the infrastructure declarations produced by evaluating that program with the current inputs.

This distinction matters for future maintenance. A loop that creates several declarations may become several explicit declarations in the generated result. The current infrastructure can be represented correctly while the original abstraction has disappeared. Adopting the generated files as maintained source is therefore a change in how subsequent infrastructure changes will be authored.

Generated output should also be separated from the directory that the synthesizer treats as disposable. Once a configuration becomes maintained source, its ownership and update process need to reflect that change. Otherwise, a later synthesis can replace edits that were intended to survive independently of the CDKTF application.

Constructs contain decisions that output alone cannot explain

The construct documentation describes an application as a tree of constructs. A construct may represent one resource or a collection, and can modify configuration created elsewhere. The output consequently includes the result of behavior that may be spread across application code, instead of only values written at the resource's declaration site.

That behavior is part of what a migration needs to understand. A required tag present in synthesized configuration may have been inserted by a reusable construct. After moving to HCL, the tag remains visible, but the mechanism ensuring its presence in future declarations may need a different implementation. Copying the current value preserves one result without necessarily preserving the rule that produced it.

This does not make synthesis an inadequate starting point. It establishes its purpose precisely. The generated configuration records what the program produced. Application code explains the reusable decisions that need to remain true when someone extends or restructures the infrastructure later.

Provider bindings add another compatibility dependency

The provider documentation distinguishes Terraform provider plugins from language bindings used by the CDKTF application. Bindings can be installed as prebuilt packages or generated for providers declared in cdktf.json. The program therefore has a typed interface to provider resources in addition to the provider executable Terraform eventually uses.

That additional interface explains why the absence of compatibility updates matters. A provider release can alter the schema that bindings represent. The language application also depends on the packages and runtime used to compile or evaluate those bindings. A maintained core Terraform executable does not automatically maintain the CDKTF-specific interpretation of every new provider capability.

Moving to HCL can remove the language-binding layer from the authoring path. It does not remove the provider dependency itself. The resulting configuration still needs provider requirements and versions appropriate to the infrastructure it describes. Keeping those versions stable during an authoring migration makes it easier to distinguish configuration changes from changes in provider behavior.

Resource addresses carry the management relationship

The resource documentation explains that application resource definitions describe the objects Terraform manages through providers. The Terraform state model then supplies the persistent relationship between configured resource instances and remote objects. A change in source language does not eliminate those existing bindings.

That is the central constraint on an HCL migration. Equivalent-looking resource settings are insufficient if the new configuration identifies a different resource instance. The migration must preserve the intended connection to objects already represented in state. Otherwise, Terraform can interpret the new declarations as requests for different management relationships.

Terraform's refactoring documentation explains that renaming or moving a resource normally appears as destroying the old address and creating a new one. A moved block records the address transition so Terraform can retain the relationship. That mechanism is relevant when the maintained HCL intentionally reorganizes generated addresses after the initial migration.

For illustrative addresses, an explicit transition has this form. Both addresses need to correspond to the actual resource instances involved in the refactor.

moved {
  from = aws_instance.old_name
  to   = aws_instance.server
}

I consider address preservation more significant than making the first generated file look idiomatic. Readability improvements can follow an understood mapping. Combining an authoring migration with unexplained renames would make a plan harder to assess because both the representation and the identities would change together.

The plan command reference distinguishes a speculative plan from a saved plan intended for application. That provides a concrete way to examine the adopted HCL before using it to change infrastructure. A plan proposing replacements after a source-language migration requires an explanation of which differences caused them. An expectation of no infrastructure change should be compared with the actual proposed operations, rather than inferred from successful synthesis. The translator accepting the program proves that it could emit configuration. The plan describes how that configuration relates to the existing managed objects in the selected environment.

Stacks also supply orchestration

The CDKTF stack documentation describes each stack as a dedicated Terraform configuration with separate state management. It also documents stack dependencies recorded in the synthesis manifest. The CDKTF CLI uses those relationships when checking deployment and destruction order.

That means a multi-stack application's behavior is not exhausted by the resource blocks in one generated file. A migration retaining separate configurations still needs an execution arrangement that respects the dependencies between them. Combining everything into one configuration changes a different architectural boundary, including the state organization, and should not be treated as a formatting consequence of generating HCL.

The retirement does not decide which replacement arrangement suits every application. It makes responsibility for that arrangement explicit. An application can retain a frozen CDKTF toolchain, move its generated configuration into maintained HCL, or adopt an independently maintained continuation if one meets its requirements. Each option needs a defined owner for compatibility and for the operational relationships previously supplied by CDKTF.

My preference is to keep the infrastructure management model understandable at the level where future changes will be reviewed. For a move to HCL, that means maintained declarations with known provider requirements and resource addresses, plus an explicit execution process for multiple states. The synthesis command supplies a useful first artifact, while those relationships determine whether the resulting configuration continues managing the intended infrastructure.