Best practices for using CDKTF, including code concepts, learning resources, and guidance for building Infrastructure as Code projects.
This article summarizes best practices for using CDKTF. We’ll revisit key CDKTF code concepts, provide further learning resources, and inspire you to build robust Infrastructure as Code projects.
When adding a component to your CDKTF project, you might wonder whether to import an existing module (from the Terraform Registry or a local file) or create your own construct.For example, an S3 backend from the Terraform Registry can be imported, or you may choose to import local files from another project. Consider the scenario where an S3 bucket requires an environment tag. In such cases, you can implement a custom construct in TypeScript that replicates Terraform’s behavior.
Below is a sample implementation of a custom construct in TypeScript:
After adding the module path to your CDKTF JSON file and setting the module name (for example, “S3 bucket with env tag”), run:
Copy
Ask AI
yarn install
Then execute:
Copy
Ask AI
yarn cdk.tf get
After running this command, the module should appear in the generated folder, allowing you to import it instead of rewriting the code manually.
For instance, you can import your module as shown below:
Copy
Ask AI
import { Construct } from 'constructs';import { App, TerraformStack } from 'cdktf';import { provider, s3Bucket } from '@cdktf/provider-aws';import * as random from '@cdktf/provider-random';import { S3BucketWithEnvTag } from './gen/modules/s3_bucket_with_env_tag';
Below is an example demonstrating the use of both the imported module and a custom construct:
Copy
Ask AI
// Configure the random providernew random.provider.RandomProvider(this, 'random-provider');const randomId = new random.id.Id(this, 'random-id', { byteLength: 4,});// Create the S3 bucket using a CDKTF resourcenew s3Bucket.S3Bucket(this, 's3-bucket', { bucket: `cdktf-demo-bucket-1-${randomId.hex}`, objectLockEnabled: true,});// Create the S3 bucket using the imported modulenew S3BucketWithEnvTag(this, 's3-bucket-with-env-tag', { name: `cdktf-demo-bucket-2-${randomId.hex}`, env: 'dev',});
Copy
Ask AI
root in ~/code on (us-east-1) took 3s
Choose between an imported module and a custom construct based on maintenance needs. If a component (like an S3 backend) rarely changes, using an existing Terraform module is acceptable. However, for components that require frequent modifications, writing them in CDKTF makes the most of TypeScript’s advanced constructs.
Integrate CDKTF into your existing project by importing Terraform modules—from local files or the Terraform Registry—and refactoring them into CDKTF code as needed. For those migrating from a traditional Terraform project, CDKTF offers a migration tool that can rewrite your project into CDKTF code automatically.Follow these steps to migrate:
Create a new directory (e.g., “CDKTF”) and navigate into it.
Install CDKTF globally:
Copy
Ask AI
npm i -g cdktf-cli
Initialize a new project:
Copy
Ask AI
cdktf init
During initialization, select TypeScript as your language and indicate that you want to migrate an existing Terraform project by providing its path. Choose the AWS and random providers if required. CDKTF will then attempt to migrate the modules automatically.A sample migrated main file might look like this:
After synthesis and resolving any duplicate imports or provider configuration issues, your project will be incrementally migrated to CDKTF code. You may need to make some adjustments, but this process supports a gradual transition from Terraform to CDKTF.For example, once you resolve duplicate import errors and correctly instantiate each provider, include the following in your stack:
Copy
Ask AI
class MyStack extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); // Configure the AWS provider new provider.AwsProvider(this, 'aws-provider', { region: 'us-east-1', // change to your preferred region }); // Configure the random provider new random.provider.RandomProvider(this, 'random-provider'); const randomId = new random.id.Id(this, 'random-id', { byteLength: 4, }); }}
Then run:
Copy
Ask AI
yarn cdktf
If the synthesis and deployment are successful, you will see resources such as the S3 buckets being created.
After deploying with imported modules, you might want to replace Terraform modules with your own CDKTF constructs. For example, define a custom construct for S3 with an environment tag as follows:
Remember that constructs are reusable components with a single responsibility. They encapsulate deployment details without mixing in business logic. For example:
Constructs can be deployed across multiple stacks and should be organized with clear dependency management. For example, if an API construct relies on a Lambda construct, ensure you have a clear grouping strategy.Stacks, on the other hand, represent deployable business functionalities. Depending on your application’s complexity, you may have a single stack or multiple stacks for microservices or distributed components.
For additional information on CDKTF, consult the official documentation and engage in community discussions. Below is a slide that highlights extra learning resources, including docs, community forums, and practical projects.
Ultimately, the best way to master CDKTF is by building real projects. This article covered best practices for importing modules versus writing your own constructs, migrating existing Terraform projects to CDKTF, and managing dependencies within constructs and stacks.Thank you for reading. We hope this guide equips you with the tools to create robust Infrastructure as Code projects with CDKTF and inspires you to build something great.