Skip to main content

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​

ChangeImpactAction Required
Node.js 22 or later requiredengines.node is >=22 in all packages. On Node.js 18 or 20, npm install reports EBADENGINERun 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 namespaceImport 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.xOptional 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.x runtime
  • Docker images are based on a Node.js 22 image
  • Check for direct nodemailer type usage and @types/nodemailer in 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.

info

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:

FileBeforeAfter (v1.6.0)
infra/libs/infra-stack.tsNODEJS_20_XNODEJS_22_X
Dockerfilenode:20-bullseye-slimnode:22-bookworm-slim + openssl
infra-local/cognito-local/Dockerfile, infra-local/appsync-simulator/Dockerfilenode:18-alpinenode:22-alpine
infra-local/serverless.ymlnodejs18.xnodejs22.x
package.json (serverless-offline)^13.3.2^13.9.0
infra/libs/pipeline-stack.tsCodeBuild image defaultruntime-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​

  1. Import nodemailer types by name and remove @types/nodemailer if 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: