Skip to content

Why We Chose Cloud Development Kit for Terraform Over HashiCorp Configuration Language for Our Infrastructure

Introduction

Ian Battaglia via Unsplash

Infrastructure as Code (IaC) is a cornerstone of modern cloud-native development, enabling teams to automate and manage their cloud resources efficiently. When developing a standardized IaC template for our Google Cloud-based enterprise services, we initially chose Terraform’s HCL (HashiCorp Configuration Language). However, as we progressed, we encountered technical limitations that led us to adopt CDKTF (Cloud Development Kit for Terraform) instead.

This post outlines the key challenges we faced with HCL, why CDKTF was a better fit, and what this decision means for our team moving forward.

The Limitations of Terraform HCL

Bootstrapping Challenges

Terraform requires a backend to store the infrastructure state, and we wanted each project to have a unique backend name incorporating the project name. Ideally, we would have defined the backend configuration dynamically using a variable. However, HCL does not allow variables within backend blocks.

This limitation left us with two unappealing options:

  1. Manually configure backends — This would be error-prone and inefficient.
  2. Use a script to modify backend configurations — This approach would be brittle, hard to maintain, and difficult to understand.
  3. CDKTF, on the other hand, does not suffer from this constraint. Since it allows backend configurations to be dynamically defined using programming languages like TypeScript, Python, and Go, we can easily parameterize backends in a clean and maintainable way.

Managing Roles Dynamically

Our Terraform setup consists of two main stacks:

  • CI Stack — Contains the pipeline responsible for managing the application stack.
  • Application Stack — Contains the actual infrastructure components for the application.

For the CI pipeline to manage infrastructure, its service account requires appropriate IAM roles. Each resource type typically requires specific roles; for example, managing a Firestore database requires the datastore.owner role.

Since application infrastructures vary across projects and evolve over time, we wanted to define the required roles alongside the resources they relate to. However, these roles must be deployed as part of the CI stack, making it impossible to define them within the application stack using Terraform HCL.

CDKTF solves this problem by offering full programming language support, allowing us to reference and define roles dynamically across different stacks without any workarounds:

// ApplicationStack.ts

ciStack.addRoleToCloudBuild(new Role("datastore.owner"), googleCloudProject)

const database = new FirestoreDatabase(this, "database", {
project: googleCloudProject,
locationId: location,
name: "(default)",
type: "FIRESTORE_NATIVE",
deletionPolicy: stage === "dev" ? "DELETE" : "ABANDON",
})


The Decision: CDKTF it is!

Given these challenges, we decided to use CDKTF for defining the infrastructure of our enterprise services. The flexibility provided by CDKTF, particularly in bootstrapping and role management, made it a superior choice over HCL.

Switching to CDKTF may introduce a slight learning curve for team members familiar only with HCL. However, the transition should be smooth since CDKTF’s structure closely mirrors HCL. Additionally, the benefits — such as improved maintainability, flexibility, and automation — far outweigh the learning effort required.

CDKTF provides us with the flexibility we need for enterprise-grade infrastructure automation. While Terraform HCL remains a powerful tool, its limitations in backend configuration and dynamic role management made it a suboptimal choice for our needs. By embracing CDKTF, we gain a more scalable and maintainable IaC approach, ensuring smoother automation and governance across our projects.

If you’re currently tasked with creating a cloud application and you’re facing a challenge related to your IaC setup, or if you’re unsure about which tool is right for you, and you want to tap into our experience, then you’re welcome to shoot me a mail at florian.wicher@andamp.io! Until then!