Ask most developers why they like the CDK and they will say “It lets me write infrastructure in my favourite programming language”.
That’s nice, but why should that be a consideration for an Infra-as-Code (IaC) tool? That’s like saying “I like Strepsils because it tastes like candy”.
ps. if you mention candy, pharmacy staff would remind you, a 40-years old man, that “these are medicines, don’t take them unless you’re sick!”. Fun fact!
In the words of Mary Poppins, “A spoonful of sugar makes the medicine go down…”. Sugar can be helpful if its purpose is to aid the delivery of medicine. But if sugar is all Mary Poppins gives to her sick kids then you might have legal grounds to call her a child abuser!
And like the sugar in my analogy above, I think most of us have been distracted by the programming language aspect of CDK, myself included. Instead, maybe we should be asking “What medicine are you feeding us?”
I’ve had more time to digest my thoughts and had worked with some clients who had success with CDK that would not have been possible with other IaC tools. I think I have managed to scratch beneath the surface and have a better understanding of where its true strengths and weaknesses lie.
For the purpose of this post, I will ignore common soundbites like:
- vendor lock-in
- lack of support for specific languages
- versioning challenges (e.g. upgrading from v1 to v2)
- abstraction problems/wrong abstractions (e.g. multiple ways to assign permissions or set up Lambda triggers)
because many others have discussed them before and ChatGPT can tell you about these already. Instead, I’m gonna add to the discord by adding some good-old human insight.
The strength of CDK
One of my initial reservations about CDK is that it’ll be difficult to adopt in an enterprise environment. Every team would want to use a different language, and that preference would translate to CDK applications.
It will therefore be difficult for the platform team to provide governance and support if they have to deal with many different programming languages that they’re not familiar with.
However, in practice, that fear hasn’t materialised. And in fact, one of CDK’s strengths turns out to be that it’s very enterprise friendly.
It’s true that an enterprise would often use different programming languages, but you’d usually find a dominant language within a given business area. And the difference and separation between different business areas can be so great that they can each have their own support system. In fact, it’s not unusual to see a large enterprise use a mix of on-premise, Azure and AWS even though individual departments would specialize in only one.
While an enterprise might not worry too much about having one solution that would work for all its departments. It cares deeply about all its departments following the compliance frameworks they have to operate within.
For an enterprise, security and compliance trump reusability any day.
CDK is very useful in this environment because:
- Developers often have to deal with a lot more infrastructure such as VPCs (practically mandatory in these environments) and serverful resources (such as RDS) than in a purely serverless environment. CDK is not focused on serverless and offers more flexibility.
- Custom CDK constructs let you encode and share security best practices and compliance measures across the organization.
I recently worked with a large financial institution in the UK. While we initially started with the Serverless framework, it soon became obvious that CDK is a better fit because of these two points.
The client is able to encapsulate the infosec requirements into custom CDK constructs and share them. That way, other teams can reuse their CDK constructs and know that they are compliant with infosec requirements.
Similarly, Matt Coulter from Liberty Mutual has often talked about how their teams are able to share high-level patterns and best practices through custom CDK constructs.
But wait, you might be wondering, “Does that ease of sharing patterns not translate outside the enterprise setting?”
It does. But smaller companies with less diverse requirements and workloads don’t need it as much. And startups can often leverage more managed AWS services and go all in on serverless offerings (including 3rd party SaaS services).
“But what about sharing patterns with the broader developer community?”
You can. And the CDK Patterns website is an example of that. But we can already share many common patterns and ideas through open-source software in general.
And sharing patterns via CDK has limitations when it comes to sharing with the broader community:
- There are more difficult (for maintainers) but accessible (for users) ways to share patterns. Remember, not everyone uses CDK. If you want to share a pattern, you want it to be accessible to most people.
- Language support is a heavy burden (for maintainers) and a barrier (for users). We can even see this with the CDK Patterns website. Not every pattern is available in all the supported CDK languages.
- When sharing patterns internally, specificity is good. “This is how we do things” is exactly what you want. When sharing patterns externally, specificity can often work against you. “Well, we have a slightly different setup, can you add an option to support X instead?” multiplied by infinity.
Call me serviceful but I rather pay for a SaaS product than bring in a CDK package that will create resources in my account. If anything, that’s the worst of both worlds:
- It’s in my AWS environment, so I’m ultimately responsible for it.
- It’s not my code, I don’t know how it works and how to fix it when it breaks.
Still, none of these detracts from the fact that CDK is great in the enterprise environment. Although, there are still cautionary practices and problems that I will go into later.
sidebar: Mike Roberts has a good article where he highlighted some challenges that make CDK a scary prospect for enterprises. For example, in enterprises where there is a clear divide between ops and dev teams. How many ops engineers would be able to support the CDK applications that are written in languages that they’re not familiar with? Especially if these CDK applications are complex and fine-tuned to the specific needs of those dev teams.
The expressive POWER
Being able to use general-purpose programming languages to describe your infrastructure is both a blessing and a curse.
As a blessing, it lets you do things that are very difficult to achieve without it. As an example, a client of mine implemented a white-label solution for their system. The solution is modular and consists of many optional parts. They often have to do custom configurations for new clients, and sometimes have to add new, bespoke components to the mix.
My client is able to capture the modular parts of the system as custom CDK constructs. And then bring them together with any bespoke parts for the final assembled CDK application.
I think this is a great demonstration of what you can do with the expressive power that CDK can offer. But it’s also worth remembering the specific context in which this power became indispensable.
After all, correlation does not imply causation.
The problems with CDK
For people moving from other frameworks such as the Serverless framework or SAM, the first thing you notice with CDK is that a lot of the capabilities you rely on simply don’t exist.
Because CDK is NOT an application development framework, it’s a development kit. Cloud Development Kit (CDK), it’s literally in the name.
A framework dictates how you do things. Whereas a library gives you the tools and you’re free to use them as you see fit.
There’s nothing wrong with either.
But as Alex DeBrie points out in his excellent blog post on CDK vs Serverless framework, there is a lot of value in having a standard structure for every application.
No standard structure for CDK applications
Without a standard structure, everyone is forced to create their own and we end up with a mire of Rube Goldberg machines across the community.
The fallout from this comes in many forms.
Onboarding new joiners are more difficult. They would have to understand two applications before they can be a productive member of the team:
- the business application
- the CDK application
This can happen even within the same company. If you don’t enforce a standard structure across teams then you will have the same challenge when people move teams. But a good question is, who gets to choose the structure everyone has to abide by?
As Alex points out, CDK enables our bad impulses to create abstractions and reusable components before we have even built the system and truly understand where the system boundaries are and which components need to be reusable.
It also distracts us away from the focus on delivering business value that serverless is supposed to give us. It reminds me of the classic nerd-sniping XDCD comic. Put an interesting engineering challenge in front of developers (ie. come up with a good structure for CDK projects) and watch things go FLOOOOM.
Worst yet, when we do come up with a good structure, we’re proud of it. That pride creates a legacy lock-in for years to come and should be a constant reminder that we lost focus.
The agency way
Ironically, one way I have seen standardised structure for CDK applications emerge is through agencies.
Think about it.
An agency chooses CDK and delivers a couple of projects. Along the way, they developed a preference for how to configure CDK projects. Compared to many homemade solutions, this is usually better because their approach has been tested in the real world. And hopefully, the agency has had experience maintaining their CDK projects over time and has learnt from those experiences.
The problem is that you now have a much tighter coupling with the agency. Not only are you relying on their technical and domain expertise for your business application. You are also tightly coupled to how they prefer to structure and deploy your entire infrastructure.
If you have to replace the agency, then you’d have a lot more work to untangle and free yourself of that coupling.
If you were to bring in another agency with a different, but equally strong opinion on how to structure CDK applications then you have a real problem on your hands. It can result in tons of extra work and friction, and potentially no end of bickering and finger-pointing.
It can be especially painful if most of the developers the agency sends you are junior and only know how to do things in the agency’s way.
Most of these downsides all stem from the same root cause. That the expressive power of a general-purpose language is a distraction where such powers are not necessary.
Having said that, all of these problems related to a lack of standard structure can be easily avoided. But it does depend on what expertise you have in-house already.
Not a framework
Recently, I have also seen quite a few people move from CDK to SST. Because, unlike CDK, it is a serverless-focused application development framework.
As I said earlier, CDK is a development kit and is focused solely on infrastructure. As such, it doesn’t offer many of the bells and whistles you will find in other frameworks. Such as:
- invoke Lambda functions locally
- tail Lambda function logs
- simulate API Gateway locally
- etc. etc.
While it’s perhaps unfair to label it a problem because that’s not what CDK was designed to do. Nonetheless, it means that you are left to pick up the slack and find solutions for yourself. Because all of these are useful for building serverless applications and help you be more productive.
Again, these are not insurmountable problems. In some cases, you might be able to find simple solutions.
For example, I use the serverless-export-env plugin regularly. It lets me capture the environment variables for my Lambda functions in a
.env file. Which I would then use in my automated tests where I test the Lambda function handlers locally. See my strategy for testing serverless architectures.
With CDK, you can instead write a
bash script to capture the environment variables into a
.env file instead.
It might not take a lot of work to solve individual problems. But the fact that it doesn’t provide any of these toolings that other frameworks offer out of the box put it at a disadvantage for teams that are looking to get things done.
Sidenote: Mike Roberts also has a list of common challenges that teams using CDK should look out for. So if you’re considering CDK or are using CDK already, then be sure to check it out.
CDK is not my preferred choice. But I’m not blind to what it can do in the right context and am happy to recommend it if the situation calls for it.
Another interesting trend I noticed from talking with other independent consultants is that, many of them also don’t prefer CDK (and practically everyone disapproves of jsii).
On the other hand, many customers love CDK. And for the longest time, I couldn’t figure out why the disparity.
Going back to my sugar analogy at the start. The consumption of sugar on the individual level is generally OK, but the hospital staffs are probably the first to notice a common trend in sugar-related problems like obesity and tooth decay.
As consultants, we have each worked with a decent no. of clients and have a broader view of the industry as a whole. And we are often called upon only when the clients are experiencing acute problems.
And like sugar, maybe the problems with CDK are only noticeable on the macro level and would only manifest themselves later in project lifecycles.
Or, maybe I’m wrong, and there are no long-term ill effects of CDK consumption.
Only time will tell.