We’ve begun to move towards the AWS CDK and here’s why

Rosh Plaha
Contino Engineering


When we talk about Infrastructure as Code (IaC), we normally think of Terraform and CloudFormation (at least from an AWS perspective). IaC has fundamentally changed the approach to managing cloud estates. There’s several benefits of course; for one, it has enabled DevOps teams to apply repeatability to deployments via templating code. And when we look at vast complex cloud footprints, being able to modularise code for reusability has made it easier than ever to understand what actually has been deployed to your accounts.

However, AWS (and others) have another option to manage your cloud infrastructure programmatically — and we at Contino have been trialling it for quite some time. So we thought we’d give an overview of our experience of the AWS CDK — coined as a developer first approach to writing IaC. We’ll do this through stating a few pro’s and con’s and a few code snippets. So let’s jump in.

What is the AWS CDK?

The AWS CDK is an open-source framework that allows you to write your Infrastructure in a language that you are already using for your application development; it’s imperative development and not a declarative configuration language like CloudFormation.

How does the CDK work?

A nice visualisation of the CDK has been taken from one of AWS’ initial blogs from 2018. The key takeaway is that you can use many supported languages to write ‘constructs’ for many supported AWS services. These can then be converted into CloudFormation templates via the ‘synth’ command, before being deployed to AWS CloudFormation.

It’s also important to note that the AWS CDK can convert code not only to CloudFormation, but also Terraform AND Kubernetes 🤯. For Terraform, see CDKtf and CDK8s.

How is the CDK kept up-to-date for all languages?

The CDK is actually written in Typescript. Using the Javascript Interop Interface (JSII), AWS can package and publish updates to the CDK to languages such as: Python, Java, C#, GoLang and .NET. That means, whenever new functionality is released by AWS — it will be available in all languages at the same time — lovely.

Some Pros

The obvious one: uniform tooling

Being able to reduce the number of languages you and your team have to learn to take ownership of your infrastructure and application code is great. And for larger organisations, you’re reducing the engineering barrier between ops and dev teams — encouraging better collaboration. We’re also interested in seeing how it can encourage the uptake of mono-repos. An interesting example we’ve seen is how an ECS stack can reference a local path to an application folder with a Dockerfile — as opposed to explicitly referencing ECR to pull down the bundled code. This couples together application and infrastructure development, that we have traditionally only seen before in serverless applications. In line 7 below, we are referencing a folder named ‘backend-api’ that points to a local Dockerfile. For smaller projects, we think this is a great way to move fast as host your containers.

Less configuration

The CDK makes some assumptions and uses defaults, so you do not have to define as much configuration as you would need to with traditional IaC. A good example of this is the setup of a VPC with some private and public subnets. For the latter to be truly public, in Terraform / Cloudformation we would need to configure a NAT Gateway, an Internet Gateway and some Route Table entries and Security Groups to ensure the inbound / outbound access. However, in the CDK example below, you can assume the creation of many of the above resources by specifying the SubnetType of PUBLIC. Again, we think this is awesome if you’re just wanting to get running as quickly as possible — such as in PoC scenarios.

Connecting AWS resources

The CDK makes it very simple to grant permissions for AWS resources to communicate with one another, without having to set up iAM permissions. For instance, if we want a Lambda to be triggered when a new file is added to S3, we can use the instance objects of both our lambda and S3 — to associate a trust relationship. The CDK, upon running `Synth`, will generate the correct restrictive iAM policies for this relationship. Historically, we’ve all definitely been pondering why our resources are throwing permission errors to access other AWS services 😭 so we’re sure this will save a lot of developer pain — who would traditionally have to fudge around with iAM permissions.

Patterns for Best Practices

There is a growing community of well defined CDK patterns. They’re well defined and easy to bolt on to your stacks. Such popular community constructs include that of CloudWatch Dashboards; its purpose is to add monitoring and observability resources to your CDK applications — almost as a side bundle. You can find out more here.

We’re also a big fan of the number of off-the-shelf constructs that AWS has published here, be it if you’re making a serverless website or a more complicated ingestion stream with firehose. We really see these as great value add to the stacks you will be building, so its definitely worth having an explore of whats available.

You can continue to use your existing tooling

A short one. As already mentioned, the CDK converts your code into CF scripts in the output folder of your repository. So once you run `deploy`, you can still utilise any existing tooling and pipelines your Organisation may already be using, such as static security suites and tests. So by adopting the CDK, you’re not rewriting the entire pipeline on day 1.

Some Cons

We’ve been kind so far — but there are definitely some areas that have caused us pain. So to give a balanced view, here are some pain points we have encountered. We’ve also included some work arounds where possible 🩹🥴.

Initial CDK setup time is time consuming

Setting up the CDK for development is initially a bit tedious — and it’s a bit more invested depending on the underlying language that you use. If you’re new to the CDK, there’s 3 installations you’re going to need:

  • AWS CLI — this is because under the hood, the CDK utilises the CLI to run commands. We’d recommend installing via brew.
  • Node Package Manager (NPM) — the CDK itself is distributed via NPM, regardless of the application language you choose e.g you’ll still need NPM even if you choose to develop in Python. Again, brew is the preferred installation approach.
  • AWS CDK — the actual libraries that you will use to compose and construct your infrastructure as code. Install link here.

However, we’ve taken away some of the pain by bundling in these dependencies in a docker image found here — especially helpful if you will be building your IaC via a pipeline.

Deployment times can be slow

The time to deploy CDK changes can be slow. We’ve experienced a few minutes delay after submitting a synth and deploy — until we can see our changes live in AWS. Of course, this is down to the necessary step to convert our code into CF and then to create a change set in AWS to update our resources. Fortunately, there is an alternative we have come across if you are specifically developing NodeJS Serverless applications — CDK watch. The beauty of this library is that it watches for lambda code changes in your javascript files and directly calls the lambda-update API with a new zip of your code. This means, in practice, local to cloud updates are synced in only a few seconds.

In summary

The CDK has a lot of compelling advantages that we encourage you to play with; it’s a great use case for moving fast with a PoC or to help developers with limited infrastructure knowledge gain exposure to Cloud configuration. We are also really interested to see how adoption develops — especially considering there are more Cloud agnostic solutions becoming available such as Pulumi. We’re excited to continue developing with the CDK and are especially excited to see how it improves the collaboration between traditional application development and DevOps.