Construct Levels

Constructs come in different levels which can help identify the level of complexity and ease of use of a construct.
L1 (CloudFormation Level 1) Constructs:
A Standard level 1 construct
  • L1 constructs map directly to the underlying AWS CloudFormation resources.
  • They provide a 1-to-1 mapping with CloudFormation resources, which means you interact with them using the same property names and values as in CloudFormation templates.

L2 (CloudFormation Level 2) Constructs:
A Standard level 2 construct
  • L2 constructs provide a higher-level abstraction built on top of L1 constructs.
  • They offer a simplified, user-friendly API that abstracts away some of the complexities of CloudFormation, making it easier to define AWS resources using higher-level programming languages.

L3 (CloudFormation Level 3) Patterns and Higher-level Constructs:
A Standard level 3 construct
  • These are constructs provided by the AWS CDK and the community that represent common design patterns and combinations of AWS resources.
  • They are pre-built constructs that encapsulate a set of lower-level constructs or L2 constructs to simplify the creation of complex infrastructures.

To further drive home this point here’s a comparison of what you write as IaC (Infrastructure as Code) and what it looks like in CloudFormation:

(!) It’s important to note that if you are following along or testing these commands out on the lifecycle-devops account, you do not accidentally run “npm publish” as this can potentially publish your lesson library to codeartifact i lifecycle-devops directly.

This is a level 1 construct written in Typescript:

  • as it uses the Cfn prefix before the function name, you can recognize it immediatelly aws a level 1 construct.
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';

export class L1LambdaConstruct extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    new lambda.CfnFunction(this, 'MySimpleFunction', {
      runtime: 'nodejs14.x',
      handler: 'index.handler',
      code: {
        s3Bucket: 'my-bucket',
        s3Key: 'code/my-lambda.zip'
      },
      role: 'arn:aws:iam::account-id:role/execution_role'
    });
  }
}

And this is the resulting cloudformation that is created from the above level 1 construct:

  • This is the construct as it is interpreted by AWS Cloudformation.
Resources:
  MySimpleFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: nodejs14.x
      Handler: index.handler
      Code:
        S3Bucket: my-bucket
        S3Key: code/my-lambda.zip
      Role: arn:aws:iam::account-id:role/execution_role

Outputs:
  LambdaFunctionArn:
    Description: "Lambda Function ARN"
    Value: !GetAtt MySimpleFunction.Arn

And this is a level 2 Construct written in Typescript:

  • This construct features additional helper methods such as “fromAsset”
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';

export class L2LambdaConstruct extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    new lambda.Function(this, 'MySimpleFunction', {
      runtime: lambda.Runtime.NODEJS_14_X,
      handler: 'index.handler',
      code: lambda.Code.fromAsset('lambda-code-directory')
    });
  }
}