CDK - A brief review of the AWS Cloud Development Kit

01/08/2023

AWS CDK Intro

AWS CDK is a library that allows you to define your infrastructure as code (IaC). If you want to setup networking, lambdas, database servers, ec2, s3, etc CDK provides a library to do that in TypeScript. CDK is available in a few languages but this post I will only focus on the TypeScript version.

CDK basically just renders TypeScript code to CloudFormation YAML templates, which AWS can use to deploy, destroy and reconfigure various services. If you're familiar with CloudFormation you'll be able to pick up CDK pretty quickly.

TypeScript IaC is perfect

AWS has a large surface area containing a wide array of complex services. Using a strongly typed language to setup these services helps developers avoid configuration mistakes and enhances the discoverability of lesser known parts of AWS. On many occasions I've increased my awareness of AWS services by using autocomplete and codepilot in my text editor. For example, I needed to spin up an app that would benefit from queue ordering by topic and TypeScript autocomplete led me to discover FIFO sqs queues. Something I probably wouldn't have discovered otherwise as I thought the service was limited to just the standard SQS queues. Lastly I think TypeScript is positioned particularly well to be used by Ai driven developer tooling like copilot due to the sematic accuracy that comes with strong typing, I expect the benefits will only increase in the future.

Alternatives

Before discovering CDK, I relied on Hashicorp's Terraform . Terraform is a great product that has many advantages over CDK.

  • Terraform is cross platform/cloud agnostic
  • Terraform is more mature
  • In my experience Terraform has been much faster and avoids weird CloudFormation stack problems
  • CDK has a large api change from v1 to v2 (v2 is a lot better, but still painful)

However for me, as a typescript developer, the benefits of typing outweigh Terraform's advantages. It's worth noting that there is a similar project cdktf that provides a similar experience to CDK in Terraform, and also there is a commercial product called Pulumi. I've heard good things about these but I don't have any experience to make an assessment.

Example - Magic Json API

To show off CDK, let's create an api that uses OpenAI text-davinci-003 to generate JSON using the request path. You can take a look at the code here magic-json-api

There are two parts to this API, the lambda and 2 cdk constructs. Let's first start by looking of the lambda code:

export const index = async (
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
  const axiosResponse = await AiLib.createCompletion({
    model: "text-davinci-003",
    prompt: `you are a generic json api.
      you have a limit of 3 items,
      write the data for ${event.path}.
      be very brief.
      you have 10 seconds to complete this task.
    `,
    temperature: 0,
    max_tokens: 500,
  });

  const response: CreateCompletionResponse = axiosResponse.data;
  const choices = response.choices;

  if (!choices[0].text) {
    throw new Error("No choices returned");
  }

  return { statusCode: 200, body: choices[0].text };
};

The above lambda just injects the HTTP path into a prompt and calls OpenAI. Nothing to see here.

Let's get to the CDK part which is really only two cdk Constructs:

export class MagicJsonApiStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: MagicJsonApiStackProps) {
    super(scope, id, props);

    const fn = new NodejsFunction(this, "MagicJsonApi", {
      projectRoot: join(ROOT),
      handler: "index",
      entry: join(ROOT, "src", "api.ts"),
      environment: { MAGIC_API_OPENAI_API_KEY: props.openaiApiKey },
    });

    const api = new LambdaRestApi(this, "MagicJsonLambda", { handler: fn, });

    new cdk.CfnOutput(this, "MagicJsonApiUrl", { value: api.url });
  }
}

This code is pretty self explanatory, we instantiate a NodejsFunction that points to the aforementioned lambda, and then reference it in ourLambdaRestApi and optionally output the api url. You'll need MAGIC_API_OPENAI_API_KEY which is the API key from OpenAI. To run you can use:

MAGIC_API_OPENAI_API_KEY=abcdef cdk deploy 

Example 1 - Beach Boys songs

I've deployed this to my blog magicapi.earlearlearl.com feel free to try it out.

GET /songs/beach-boys/best.json

{
  "songs": [
    { "title": "Good Vibrations", "artist": "The Beach Boys" },
    { "title": "Surfin' USA", "artist": "The Beach Boys" },
    { "title": "Kokomo", "artist": "The Beach Boys" }
  ]
}

Warning: OpenAI only got Good Vibrations correct

Example 2 - Worst uses of a broom

GET /worst-ways-to-use/broom.json

{
  "data": [
    {
      "title": "Sweeping Dust Into the Air",
      "description": "Using a broom to sweep dust into the air instead of into a dustpan."
    },
    {
      "title": "Using a Broom to Clean Spills",
      "description": "Using a broom to clean up spills instead of a mop or cloth."
    },
    {
      "title": "Using a Broom to Sweep Snow",
      "description": "Using a broom to sweep snow instead of a shovel."
    }
  ]
}

Conclusion

CDK is very useful for AWS users and helps developers leverage types in IaC code, making it very easy to iterate on fullstack projects.

Even my blog is built with Cdk using ci/cd github actions 😎.

Broom in space