Skip to content

What Are AWS CDK Constructs, Stacks and How To Use Them

When getting started with the AWS CDK, one of the most confusing aspects are the new terminologies of apps, stacks and constructs. I will compare constructs vs stacks vs apps to explain what they are and when to use them.

At a glance

WhatWhat is itWhen to use it
Constructs Represent the AWS resources you want to create.Use to define the resources you want to create.
StacksRepresent an AWS CloudFormation template and all its associated assets.Stacks should be used as units of deployments since stacks can be deployed separately, but resources within stacks can not be deployed separately. Separating stacks by their deployment frequency is a good idea.
AppThe root object – can contain several stacks which can share resources with each other. An app should correspond to all the stacks an application requires to be fully functional.
A table comparing apps vs stacks vs constructs
A sample of how constructs, stacks and apps may be organised

Constructs

AWS CDK constructs at their core represent one or more AWS resources – however, these come in three common and distinct flavours:

Level 1 Constructs

What are they

Level 1 constructs correspond directly to a single AWS resource, exactly how it is described within AWS Cloudformation. Examples of this would a single S3 Bucket, a Lambda function and a DynamoDB table.

When to use

When a new AWS service or resource is added to the AWS CDK, it initially is added as a level 1 construct. However, they are usually then followed by superior level 2 constructs described below. Level 1 constructs should primarily be used when level 2 constructs are not available.

Level 2 Constructs

What are they

Level 2 constructs are built on top of level 1 constructs, however, these include quality of life and usability improvements around a particular service. The lambda function construct is a prime example of this. The level 1 Lambda function construct requires a pre-existing s3 bucket object, containing the compressed Lambda source code and will only create the Lambda function resource itself.
The level 2 construct, however, requests the location of the uncompressed source code locally, automatically uploads this to an S3 bucket for you and then deploys this within the lambda function. Additionally, it will enable CloudWatch logs out of the box and give the lambda function the correct associated permissions.

When to use

Level 2 constructs are what you will mostly be working with when creating your AWS solution. The AWS CDK team put a lot of effort into providing these and are generally of very high calibre. It is possible to write your own but it is unlikely this will be required.

Level 3 Constructs

What are they

Level 3 constructs are opinionated units of reusable code which often deliver a service. Open source level 3 constructs are available from AWS Solutions Constructs – an extension to the CDK, CDK Patterns – a library of well-architected patterns, Construct Hub – a library of open-source constructs and some even come out of the box with the CDK – these are appended with ‘patterns’ to make them identifiable. Two examples are shown below:

A simple web service using API Gateway, Lambda and DynamoDB
A Static React/Angular Single Page Application Website

When to use

If you are able to find a level 3 construct which matches your desired architecture – you should use this level 3 construct. However, if one does not exist, you should evaluate whether your specific pattern is likely to be reused – either within your code or within your organisation. If the answer is yes, then you should be writing your own level 3 construct from the available level 1 and 2 constructs. If you are working on any enterprise or large scale project, you will find the majority of your time spent with the CDK is spent creating level 3 constructs.

Bonus: Tips for Building L3 Custom Constructs

While a construct should be opinionated and achieve one goal very well, it is important to add properties to allow configuration of the underlying resources and expose the resources created. For example, if you could not configure a lambda function’s resources, it would prevent anyone who needs a larger function from using your construct.

But do not expose excessive amounts of the underlying infrastructure to the user to nullify any abstractions you provided. Recall how the Lambda Function construct automatically uploads the source code to an S3 bucket and then uses this in the lambda function. Providing the object name or path of the uploaded source code as a configurable option would be irrelevant to this construct and unnecessarily leak this abstraction to the user.

Stacks

What are they

Stacks correspond exactly to one single CloudFormation stack and the corresponding assets. The defining feature of a stack is that it is a unit of deployment – you can deploy stacks independently of each other, but all of the resources within a stack will be deployed together.

When to use

You should use stacks to combine resources which should be deployed together. A common split would be having frontend and backend resources in a separate stack. Additionally, having frequently changes and infrequently changed resources in separate stacks. For example, you may not want your infrequently changing networking and database layers in the same stack as your frequently changing compute and content layers.

Apps

Apps are the root object and contain stacks. The key feature here is that stacks housed within the same app can share resources with each other. For example, a backend stack can share resources with the front end stack. Multiple apps can exist in a single project folder, however:

  • CDK can only deploy or synthesise one app at a time, whereas it can deploy multiple stacks.
  • Two apps can not be defined in the same file – they must live in separate files
  • Two apps can not reference each other’s resources

When to use

This is always the root object in a CDK app and should contain all the stacks required for an application. Whether or not to house a stack in a separate app comes down to whether it needs to share resources with any other stacks. Examples of this could be load testing stacks and infrastructure testing stacks – these would most likely not need to have access to resources within the front end and backend stacks so could sit in a different app.

Leave a Reply

Your email address will not be published.