Introduction Link to heading
So… we have a bunch of small CDK construct libraries that are mostly just a Lambda function. We added integration tests, like you do these days. And renovate, because we aren’t barbarians. And then I got this error while trying to address stupid nodejs runtime issues:
TypeError: (0 , core_1.determineLatestNodeRuntimeName) is not a function
The root cause is simple: CDK’s alpha packages (@aws-cdk/integ-tests-alpha, @aws-cdk/integ-runner) must exactly match your aws-cdk-lib version. And when you’re using Projen with experimentalIntegRunner: true, it adds these packages as latest, which works great until it doesn’t.
This is particularly relevant when working with Lambda-centric constructs, where CDK version directly impacts which Node.js runtimes you can use.
Understanding cdkVersion in Construct Libraries Link to heading
In a construct library (as opposed to a CDK app), cdkVersion controls both what you promise to consumers and what you test against:
Peer Dependency - Your Promise
"peerDependencies": {
"aws-cdk-lib": "^2.171.0"
}
That caret means “I work with 2.171.0 and anything compatible with it.”
Dev Dependency - Your Reality
"devDependencies": {
"aws-cdk-lib": "2.171.0"
}
No caret. This is the exact version you’re building and testing with.
The Mismatch Problem Link to heading
I’ve definitely approved PRs where someone pinned a newer version in deps while leaving cdkVersion at an older value:
cdkVersion: '2.1.0', // We claim to support this
deps: ['aws-cdk-lib@2.112.0'] // But we actually require this
I’m guessing this was a dev who didn’t understand the semantics of cdkVersion and another dev (me) who wasn’t on top of the review.
The fix is straightforward - be honest about your requirements:
cdkVersion: '2.112.0', // This is the minimum we actually support
The Integration Test Package Problem Link to heading
This is the real issue. When you enable experimentalIntegRunner: true in Projen, it generates:
"@aws-cdk/integ-runner": "latest",
"@aws-cdk/integ-tests-alpha": "latest"
Alpha packages follow a strict versioning pattern:
- CDK 2.171.0 needs
@aws-cdk/integ-tests-alpha@2.171.0-alpha.0 - CDK 2.225.0 needs
@aws-cdk/integ-tests-alpha@2.225.0-alpha.0
The alpha version must exactly match your CDK version. When @aws-cdk/integ-tests-alpha is newer than aws-cdk-lib, it tries to call APIs that don’t exist yet, hence the “is not a function” error.
Package Manager Overrides Link to heading
Modern package managers support overriding dependency versions. In pnpm (and similar mechanisms exist in npm and yarn), you can force the correct versions:
// .projenrc.ts
const cdkVersion = '2.171.0';
const project = new clickupCdk.ClickUpCdkConstructLibrary({
cdkVersion: cdkVersion,
experimentalIntegRunner: true,
// ... other config
});
// Override integ test dependencies to match CDK version
project.package.addField('pnpm', {
overrides: {
'@aws-cdk/integ-runner': `${cdkVersion}-alpha.0`,
'@aws-cdk/integ-tests-alpha': `${cdkVersion}-alpha.0`,
},
});
project.synth();
After running pnpm projen, the alpha packages will be pinned to match your CDK version exactly, regardless of what version Projen tried to specify.
Choosing the Right CDK Version for Lambda Constructs Link to heading
When you’re building constructs that include Lambda functions, your CDK version determines which Node.js runtimes are available:
| Node Runtime | Lambda Support | CDK Support | EOL Date |
|---|---|---|---|
| Node 18 | Nov 2022 | 2.50.0+ | Apr 2025 |
| Node 20 | Nov 2023 | 2.112.0+ | Apr 2026 |
| Node 22 | Nov 2024 | 2.171.0+ | Apr 2027 |
If your Lambda construct needs Node 22, you must use CDK 2.171.0 or newer. For a library intended for general use, I’d recommend picking a version that’s 2-6 months old and includes the Node runtime you need. Going too new forces consumers to upgrade; too old and you’re missing bug fixes.
Lambda Runtime Specification Link to heading
Generally, I don’t really care what version of Node I’m running on. Because generally, I’m running very small Lambda functions - a couple hundred LoC or less. And, again, generally, we aren’t really doing anything that Node 8 wouldn’t work just fine for.
So… generally… what I really want is for Node runtime to Not Be A Problem.
CDK’s Runtime.NODEJS_LATEST and the @aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion feature flag now make this possible. But that’s a whole saga unto itself, which I cover in The NODEJS_LATEST Saga.
The TL;DR: unless you have a good reason to care about your Node.js runtime version, enable the feature flag and stop thinking about it.
Integration Test Workflow Link to heading
With versions properly aligned, the integration test workflow is:
# Unit tests (no AWS required)
pnpm test
# Integration tests (deploys to AWS)
export AWS_PROFILE=your-profile
pnpm integ
# Update snapshots after changes
export AWS_PROFILE=your-profile
pnpm integ:update
One important note: when you upgrade CDK versions, integration test snapshots will change. CloudFormation templates evolve between versions - deprecated features are removed, defaults change, the templates improve. This is expected. Review the changes, make sure they’re reasonable, and commit the updated snapshots.
Conclusion Link to heading
Managing CDK versions in construct libraries with Lambda functions comes down to:
- Be honest about minimum versions. Set
cdkVersionto the actual minimum you support. - Pin alpha packages exactly. Use package manager overrides to lock
@aws-cdk/integ-tests-alphato your CDK version. - Choose CDK versions based on Lambda runtime needs. Your construct’s Lambda functions determine your minimum CDK version.
The integration testing alpha package version mismatch is annoying, but once you understand the pattern and set up overrides, it’s a solved problem.