What are CDK Constructs?
CDK constructs are the fundamental building blocks of the AWS CDK.
They are reusable components that represent cloud resources (like S3 Buckets, Lambda Functions, or VPCs).
Types of constructs
CDK Constructs come in three different levels:
- Level 1 constructs → Not used frequently because most AWS resources are migrated to L2;
- Level 2 constructs → Most common type of construct;
- Level 3 constructs → Highest level of abstraction. Usage is very circunstancial.
L1 - Low level constructs
L1 constructs are a direct representation of CloudFormation resources.
In L1 Constructs, we, the developers must manually configure all the required properties.
Here is a Python example:
s3.CfnBucket(self, "L1Bucket", lifecycle_configuration=
s3.CfnBucket.LifecycleConfigurationProperty(
rules=[
s3.CfnBucket.RuleProperty(
status="Enabled"
expiration_in_days=3
)
]
)
)L2 - AWS Resources at a higher level
L2 constructs are an abstraction over L1 constructs.
When using L2 constructs, code is simplified behind abstraction, we do not need to define every property because L2 constructs are using L1 constructs that define these under the hood.
Here is a Python example:
s3.Bucket(self, "L2Bucket", lifecycle_rules=[
s3.Lifecycle_Rule(
expiration = Duration.days(3)
)
])Note: This example will effectively deploy the same bucket as the previous one, however, the code is much simpler when comparing against the L1 example.
L3 - Patterns
L3 constructs are a combination of multiple L2 or L1 constructs.
They combine multiple types of resources to help with various tasks.
What are Constructs composed of?
CDK Constructs are composed by the following:
- Scope - Required - Defines the parent of the construct.
- ID - Required - Defines the Construct id of the construct.
- Props - Optional - Defines additional configuration properties specific to the construct.
Here is an example using Python:
`s3.Bucket(
self, # Scope: current stack
"MyBucket", # Construct ID
removal_policy=cdk.RemovalPolicy.DESTROY, # Props
bucket_name="my-unique-bucket-name" # Props
)What are construct IDs?
Each CDK Construct has a unique id associated within it’s parent Construct (i.e. Within the stack or another construct).
These IDs are used to identify and reference the constructs.
Think of Construct IDs as primary keys for each Construct.
Example:
bucket = s3.Bucket(self, "MyBucket")In this snippet, the S3 Construct has the Construct id MyBucket.
What are Logical IDs?
Even though, in the previous example, the Construct id was MyBucket, CDK will generate a logical id composed of the Construct id, plus, a random suffix. Something like MyBucket678D523G.
This logical id is the unique identifier for a resource in the CloudFormation template that CDK generates with cdk synth.
For instance, the previous example will generate a logical id such as this one:
"Resources": {
"MyBucketF68F3FF0": {
"Type": "AWS::S3::Bucket",What are Physical IDs?
The Physical id represents the “real-world name” or identifier of the resource in AWS (e.g., the name of an S3 Bucket, the ARN of a Lambda function, or the ID of a DynamoDB table).
If the Physical id is not explicitly defined in the CDK Construct definition, then, a Physical id will be generated following this pattern:
{StackName}{ConstructID}{Hash}
Example:
class CdkCrashcourseStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
account = self.account # 000000000000
region = self.region # eu-west-1
s3.Bucket(
self,
"MyBucket",
bucket_name=f"my-bucket-{account}-{region}",
)This will create a bucket with a Physical id of my-bucket-000000000000-eu-west-1.
However, this example:
class CdkCrashcourseStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
s3.Bucket(
self,
"MyBucket",
)Will generate a Physical id similar to mystack-mybucketf68f3ff0-brtkb3xldatu.