Migration Guide: v1.6.0
This guide helps you upgrade from v1.5.x to v1.6.0. Version 1.6.0 requires Node.js 22 or later in every published package. Application logic is not affected, but your local environment, CI, Lambda runtime and Docker images must move to Node.js 22.
Release Date
2026-11-03
Breaking Changes Summary
| Change | Impact | Action Required |
|---|---|---|
| Node.js 22 or later required | engines.node is >=22 in all packages. On Node.js 18 or 20, npm install reports EBADENGINE | Run apps, Lambda functions and Docker images on Node.js 22.23.4 or later |
| nodemailer 10 (core) | nodemailer ships its own types; the default export is no longer a namespace | Import nodemailer types by name and remove @types/nodemailer (only if you use nodemailer directly) |
| CLI templates (new projects only) | New projects use NODEJS_22_X, node:22-bookworm-slim, node:22-alpine and nodejs22.x | Optional for existing projects: update the same places by hand |
Why Node.js 22?
Node.js 18 and 20 are end of life and will not receive the fix for CVE-2026-111497 (Node2Shell), a remote code execution vulnerability in the Brotli decoder bundled with Node.js. The fix ships in Node.js 22.23.4, 24.22.1 and 26.12.1. @mbc-cqrs-serverless/core also now depends on nodemailer 10, which itself requires Node.js 20 or later. The framework CI tests Node.js 22 and 24.
Pre-Migration Checklist
Before upgrading, verify the following:
- Node.js 22.23.4 or later is installed locally
- CI workflows use Node.js 22 or later
- Lambda functions and layers use the
nodejs22.xruntime - Docker images are based on a Node.js 22 image
- Check for direct
nodemailertype usage and@types/nodemailerin your codebase - Run the full test suite after upgrading
Breaking Change 1: Node.js 22 or Later Required
What Changed
All published @mbc-cqrs-serverless/* packages now declare engines.node as >=22. On Node.js 18 or 20, npm install reports an EBADENGINE warning, and the install fails when engine-strict is enabled.
npm warn EBADENGINE Unsupported engine {
npm warn EBADENGINE package: '@mbc-cqrs-serverless/core@1.6.0',
npm warn EBADENGINE required: { node: '>=22' },
npm warn EBADENGINE current: { node: 'v20.x.x', npm: '10.x.x' }
npm warn EBADENGINE }
Migration Steps
Step 1: Local development
Install Node.js 22.23.4 or later. If you use nvm:
nvm install 22
nvm use 22
node --version # Must be v22.23.4 or later
If your project has an .nvmrc, .node-version or engines field, update it as well:
{
"engines": {
"node": ">=22"
}
}
Step 2: CI
Update the Node.js version in your CI workflows:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '22.x'
Step 3: Lambda runtime
Update the runtime of your Lambda functions and layers.
AWS CDK:
// Before (v1.5.x)
compatibleRuntimes: [cdk.aws_lambda.Runtime.NODEJS_20_X],
runtime: cdk.aws_lambda.Runtime.NODEJS_20_X,
// After (v1.6.0)
compatibleRuntimes: [cdk.aws_lambda.Runtime.NODEJS_22_X],
runtime: cdk.aws_lambda.Runtime.NODEJS_22_X,
Serverless Framework (serverless.yml, including infra-local/serverless.yml):
provider:
name: aws
runtime: nodejs22.x
For local development with serverless-offline, use serverless-offline ^13.9.0 or later so that the nodejs22.x runtime is supported.
npm install --save-dev serverless-offline@^13.9.0
CDK pipeline (infra/libs/pipeline-stack.ts):
If you deploy through the scaffolded CDK pipeline, pin the CodeBuild Node.js version so that npm ci, the tests, the synth and the layer build run on Node.js 22 instead of the CodeBuild image's default, which can change:
const pipeline = new CodePipeline(this, idName + 'PipelineV3', {
selfMutation: true,
// Pin every CodeBuild project in the pipeline to Node.js 22
codeBuildDefaults: {
partialBuildSpec: BuildSpec.fromObject({
phases: { install: { 'runtime-versions': { nodejs: '22' } } },
}),
},
// ...
})
Step 4: Docker images
Move your Docker images to a Node.js 22 base image. If you switch the application image to node:22-bookworm-slim and use Prisma, install openssl in every stage that runs Prisma, because Prisma's query engine needs libssl, which bookworm-slim does not ship.
# Before (v1.5.x)
FROM node:20-bullseye-slim
# After (v1.6.0)
FROM node:22-bookworm-slim
# Prisma's query engine needs libssl, which bookworm-slim does not ship
RUN apt-get update -y && apt-get install -y --no-install-recommends openssl && rm -rf /var/lib/apt/lists/*
The local emulator images under infra-local/ (for example cognito-local and appsync-simulator) can move to node:22-alpine:
# Before
FROM node:18-alpine
# After
FROM node:22-alpine
Breaking Change 2: nodemailer 10 Types
What Changed
@mbc-cqrs-serverless/core now depends on nodemailer 10. nodemailer 10 ships its own type definitions, and its default export is no longer a namespace, so type references such as nodemailer.SendMailOptions no longer compile.
If your application only uses EmailService from @mbc-cqrs-serverless/core, no code changes are required.
Migration Steps
Step 1: Find usages
grep -rn -E "nodemailer\.(SendMailOptions|Transporter|SentMessageInfo)" --include="*.ts" src/ test/
grep -n "@types/nodemailer" package.json
If no results are found, no action is required.
Step 2: Import the types by name
Before:
// Before (v1.5.x, nodemailer 9 with @types/nodemailer)
import nodemailer from 'nodemailer';
const mailOptions: nodemailer.SendMailOptions = {
from: 'noreply@example.com',
to: 'user@example.com',
subject: 'Hello',
};
After:
// After (v1.6.0, nodemailer 10)
import nodemailer, { SendMailOptions } from 'nodemailer';
const mailOptions: SendMailOptions = {
from: 'noreply@example.com',
to: 'user@example.com',
subject: 'Hello',
};
Apply the same change to Transporter and SentMessageInfo.
Step 3: Remove @types/nodemailer
npm uninstall @types/nodemailer
CLI Templates (New Projects Only)
Projects created with mbc new on v1.6.0 use Node.js 22 out of the box. Existing projects are not changed. To follow, update the same places by hand:
| File | Before | After (v1.6.0) |
|---|---|---|
infra/libs/infra-stack.ts | NODEJS_20_X | NODEJS_22_X |
Dockerfile | node:20-bullseye-slim | node:22-bookworm-slim + openssl |
infra-local/cognito-local/Dockerfile, infra-local/appsync-simulator/Dockerfile | node:18-alpine | node:22-alpine |
infra-local/serverless.yml | nodejs18.x | nodejs22.x |
package.json (serverless-offline) | ^13.3.2 | ^13.9.0 |
infra/libs/pipeline-stack.ts | CodeBuild image default | runtime-versions nodejs: 22 |
package.json, infra/package.json (@types/node) | ^20 | ^22.20.5 |
The template's dependency overrides now also pin proxy-addr 2.0.8, body-parser 1.20.9 / 2.4.0 and multer 2.5.0, and raise qs to ^6.16.1 (the minimum that the patched body-parser requires). You can add the same overrides to an existing project to clear these advisories.
Upgrade Steps
Step 1: Switch to Node.js 22
Follow Breaking Change 1 for local development, CI, Lambda and Docker.
Step 2: Update Dependencies
npm install \
@mbc-cqrs-serverless/core@^1.6.0 \
@mbc-cqrs-serverless/tenant@^1.6.0 \
@mbc-cqrs-serverless/master@^1.6.0 \
@mbc-cqrs-serverless/sequence@^1.6.0 \
@mbc-cqrs-serverless/task@^1.6.0 \
@mbc-cqrs-serverless/cli@^1.6.0
Step 3: Apply Code Fixes
- Import nodemailer types by name and remove
@types/nodemailerif used (see Breaking Change 2)
Step 4: Run Tests and Deploy
npm run test:cov
After deploying, confirm in the AWS Lambda console that your functions run on the nodejs22.x runtime.
Security Fixes in v1.6.0
- Clear high and critical advisories in production dependencies: proxy-addr 2.0.8, body-parser 1.20.9 / 2.4.0, multer 2.5.0, nodemailer 10.3.1, @modelcontextprotocol/sdk 1.32.2, zod 4.6.7
Support
If you encounter issues during migration:
Related Documentation
- Changelog v1.6.0 - v1.6.0 release notes
- Installation - System requirements
- Email Service - Sending email with
EmailService - Deployment Guide - Deploying to AWS