When I started using AWS Lambda, my team used the serverless framework to describe our AWS resources. This is easing things a lot compared to writing only plain CloudFormation templates. But still, there was a lot of CloudFormation to be written. This used to be nobody's favourite task. Then CDK came to the rescue.
Writing CloudFormation sucks. It is highly repetitive, lengthy, and slow. Code completion is really limited and I just cannot manage to remember the syntax of those intrinsic functions.
So nobody needed to convince me when CDK came along. Finally, there is code completion, extraction of repetitive parts, and there are constructs. CDK constructs are infrastructure building blocks for your application - they can represent a single CloudFormation resource or represent a higher-level component consisting of multiple resources. They bundle things that usually go together - like a Lambda Function with LogGroup and execution role. These constructs reduce the amount of code needed to describe a stack. So CDK does not mean describing CloudFormation resources in a programming language. It also provides an abstraction above CloudFormation resources.
Also, CDK allows for easy connection between constructs. There is a method to grant read access to a DynamoDB table for a Lambda function. This is so much more convenient than CloudFormation.
Yes, there are downsides, too. CloudFormation usually has no surprises when it comes to structure. There is not much freedom there, so CloudFormation templates are usually lengthy but still rather easy to read. The freedom of a higher-level programming language leaves much more room to structure things in different ways. So it usually takes a bit until I understand a CDK app that I did not write myself.
But after all the benefits outweigh the downsides by far.
By using your custom CDK construct library you can get even more advantages out of CDK. When I say custom CDK construct library I mean writing your own constructs that you package into a library and make them available in your organization.
So let's look into what is in for you.
When you work in an organisation larger than just a few developers you will have conventions around AWS resources. Something like "Enable encryption at rest for your SQS queue!" or "Point-in-time recovery should be enabled for every DynamoDB table!". Usually, such conventions are documented in a guideline somewhere. You rely on the discipline of your developers that those conventions are actually applied. Maybe you even write some code that checks your resources regarding those conventions and raises alarms if the rules are violated. This is a little better. Now you can be sure that those conventions are applied - but only after they already have been deployed.
I find it a little smarter if developers are incentivised to consider those conventions by making their lives easier. With CDK you can have your custom construct wrapping the DynamoDB Table construct which defaults some settings according to your conventions. Developers will like to use this because they have to worry about a few things less.
Such convention constructs are a good start, since they are easy to write.
Often there are standard ways of doing things in an organisation. Here are a few examples.
Logs for Lambda functions have a retention of 14 days and are always shipped to ElasticSearch for central log aggregation
Every REST API is using a subdomain of our corporate domain (requiring DNS Records and a certificate)
For every Lambda function, we want an alarm when errors are logged
Such standard cases result in a lot of code that is copied over and over again. Those are perfect candidates for custom constructs.
So our custom Lambda function construct can create the Lambda function and make sure that the LogGroup is configured appropriately. We can also offer an aspect that can be added to a stack to add MetricFilters and Alarms for error log entries in every Lambda LogGroup.
In the end, we have saved a few lines of code in many projects, developers have to worry about fewer things, and we are making sure that best practices are applied.
Your CDK construct library can also be the go-to place for important constants. Usually, constants around the AWS accounts and shared resources are scattered around different pieces of documentation. So developers need to go to various places to look them up. Often such values are then hard-coded in the CloudFormation or the CDK configuration.
We can add those constants to our custom CDK construct library. So they are easy to find and access. Also, they do not have to be copied into application code. Those constants can be ids of AWS accounts, the standard destinations for alarms, or the webhooks of important slack channels that you want to post to from your AWS infrastructure.
With these constants, information moves closer to the place of use and thus less time is spent searching for this information in the documentation.
A CDK construct library can be something a developer community can share and care about together. This can foster collaboration across teams and can start important conversations about lessons learned and best practices.
You are working in a polyglot environment - also this is not an obstacle. It is possible to write your CDK construct library once in TypeScript and use jsii to deliver polyglot libraries from it (Go, Java, Python). Jsii is also used by the CDK project itself to deliver the different language bindings it offers.
I hope you cannot wait now to create your own customer CDK construct library. Just head over to your favorite terminal and enter.
cdk init lib - language=typescript
You can also use projen to jump into developing your custom construct library.
Furthermore the CDK Workshop is a good start for starting to write your first own construct. It contains an example for writing a construct.