| name | cds10-migration |
| description | Use when migrating a SAP CAP project to CDS 10 / @sap/cds 10 (released June 2026): deprecated APIs, breaking changes, Node.js 22 minimum, consolidated service APIs, bypass drafts by default, ieee754compatible defaults, Vitest/ESM migration, native SQLite/Fetch defaults, or preparing for the CDS 10 major version upgrade.
|
| metadata | {"version":"1.1.0","keywords":["CDS 10","cds10","migration","upgrade","breaking change","deprecated","Node.js 22","Node.js 24","bypass draft","ieee754","service results","cds upgrade","Vitest","ESM"],"related":{"cds9-migration":"migrating from CDS 8 or earlier — do that first before targeting CDS 10","testing":"verify migration with Vitest (Jest deprecated in CDS 10 roadmap)","service-handlers":"consolidated write-result API in CDS 10","fiori-draft":"bypass drafts by default change in CDS 10"}} |
CDS 10 Migration — CAP Best Practices
Primary reference: https://cap.cloud.sap/docs/releases/2026/jun26
Migration guide: https://cap.cloud.sap/docs/releases/migration/cds10
Package version requirements
{
"engines": { "node": ">=22" },
"dependencies": {
"@sap/cds": "^10",
"@sap/cds-dk": "^10",
"@sap/cds-mtxs": "^4",
"@cap-js/sqlite": "^3",
"@cap-js/hana": "^3"
}
}
⚠️ Don't mix versions: Never use @sap/cds 10.x with @sap/cds-mtxs 3.x or @cap-js/hana 2.x — versions must align.
CAP Java 5 requires JDK 21 (minimum) or JDK 25 (recommended) and Spring Boot 4.1+.
Use cds upgrade to check your project
npm install -g @sap/cds-dk
cds upgrade
The cds upgrade tool (Alpha in CDS 10) scans your project for breaking changes and provides migration guidance for each finding.
Step-by-step migration checklist
Step 1: Meet Node.js requirements
| Node.js version | Status in CDS 10 |
|---|
| Node.js v20 | Not supported (EOL April 2026) |
| Node.js v22 | Minimum required |
| Node.js v24 | Recommended (Active LTS) |
| Node.js v26 | Already tested, usable in dev |
node --version
Step 2: Upgrade packages
npm install @sap/cds@latest @sap/cds-dk@latest
npm install @cap-js/sqlite@latest @cap-js/hana@latest
npm install @sap/cds-mtxs@latest
Step 3: Fix CDS compiler errors — improved checks
The CDS compiler now reports security annotation mismatches as errors (not warnings):
// ❌ Typo in artifact name — was a warning, now an error
annotate AdmnService with @requires: 'admin'; // "AdmnService" doesn't exist
// ❌ Duplicate element extension — now an error
extend MyEntity with { field: String; };
extend MyEntity with { field: Date; }; // duplicate!
// ❌ Invalid default on structured element — now an error
type Address { street: String; city: String; }
entity Foo { addr: Address default 'Berlin'; }
Run to find all errors:
cds compile '*'
Step 4: Handle breaking behavior changes
A. Bypass Drafts by Default (bypass_draft: true)
Impact: Direct access to active entities now skips draft choreography by default.
GET /odata/v4/Orders(123)
PATCH /odata/v4/Orders(123)
DELETE /odata/v4/Orders(123)
If you need the old behavior (always go through draft choreography):
// in srv/cat-service.js
cds.fiori.bypass_draft = false
Handler impact: Validation handlers must now handle both draft AND active entity paths:
this.on('PATCH', Orders, req => {
})
B. Consolidated Write Results
INSERT now returns an iterable array with generated keys:
const result = await INSERT.into(Products).entries(
{ title: 'Book 1', price: 29.99 },
{ title: 'Book 2', price: 19.99 }
)
const [book1, book2] = [...result]
UPDATE/DELETE return { affected: number }:
const { affected } = await UPDATE(Products, id).with({ price: 24.99 })
const { affected: deleted } = await DELETE.from(Orders).where(...)
Handler note: Access input via req.data in handlers — don't rely on the return value.
C. IEEE754Compatible enabled by default
Decimal and Int64 fields now return as strings (not numbers):
In TypeScript/client code, parse as needed:
const amount = parseFloat(order.amount)
const price = new Decimal(order.price)
Disable if needed (⚠️ not recommended):
// srv/cat-service.js
cds.env.build.ieee754compatible = false
D. srv.entities — now a getter, not a callable
const { Books } = srv.entities()
const { Books } = srv.entities
E. Removed compatibility flags
These flags have been removed in CDS 10:
| Flag | Alternative |
|---|
cds.compat.consistent_params | Already built-in |
cds.compat.compat_save_drafts | Use cds.fiori.bypass_draft: false instead |
cds.compat.assert_not_null | Stricter validation now default |
CAP Java migration (Spring Boot 4.1+)
| Requirement | CDS 9 | CDS 10 |
|---|
| JDK | 17, 21 | 21 minimum, 25 recommended |
| Spring Boot | 3.2, 4.0 | 4.1 minimum |
| Spring Security | 6.x | 7.0+ |
| Maven | 3.8.8+ | 3.9.14+ |
Automatic migration with OpenRewrite
CAP Java 5 provides OpenRewrite recipes that automate the bulk of required code changes:
mvn org.openrewrite.maven:rewrite-maven-plugin:run \
-Drewrite.recipeArtifactCoordinates=com.sap.cds:cds-services-recipes:5.0.0 \
-Drewrite.activeRecipes=com.sap.cds.services.migrations.Cap_5.0
This handles most deprecated API replacements and property migrations automatically.
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<spring-boot.version>4.1.0</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>com.sap.cds</groupId>
<artifactId>cds-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
Going Native — third-party dependencies removed
In CDS 10 these replacements are defaults (no longer opt-in feature flags):
| Removed dependency | Replaced by |
|---|
axios | Node-native Fetch API |
better-sqlite3 | Node-native node:sqlite |
generic-pool | Built-in connection pool |
@sap-cloud-sdk/http-client | Native Fetch (in dev; Cloud SDK still needed for production OAuth) |
Total footprint reduction: ~112 packages, ~23 MB. No code changes needed.
In production or hybrid scenarios that need BTP Destination OAuth: @sap-cloud-sdk/http-client is still required — add it explicitly with npm add @sap-cloud-sdk/http-client.
Vitest migration (Jest deprecated)
CDS 10 recommendation: Use Vitest instead of Jest:
npm uninstall jest
npm install --save-dev vitest chai
import { defineConfig } from 'vitest/config'
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
export default defineConfig({
test: {
globals: true,
testEnvironment: 'node',
coverage: {
provider: 'v8'
}
}
})
Why: Chai v6 (used in CAP tests) has full support only with Vitest; Jest has partial compatibility.
Health check — verify your migration
cds compile '*'
npm test
grep -r "class.*ApplicationService" srv/
grep -r "return super.init()" srv/
grep -r "bypass_draft" . --include="*.js"
grep -r "from 'jest'" test/
grep -r "srv.entities()" srv/
Quick migration path
- Node.js: Upgrade to v22+
- Packages:
npm install @sap/cds@latest
- Compile:
cds compile '*' — fix all errors
- Tests: Update Jest → Vitest (if applicable)
- Handlers: Verify
return super.init() in init()
- Results: Handle new write result shapes (INSERT iterable, UPDATE/DELETE
{ affected })
- Drafts: Test if
bypass_draft: true default works or needs false
- CAP Java: Upgrade JDK to 21, Spring Boot to 4.1
- Run tests:
npm test
- Deploy: Follow your deployment pipeline
Common mistakes to avoid
- ❌ Mixing @sap/cds 10.x with @cap-js/sqlite 2.x or @sap/cds-mtxs 3.x
- ❌ Forgetting Node.js v22 requirement (v20 is EOL)
- ❌ Not handling new write result shapes (INSERT iterable, UPDATE/DELETE
{ affected })
- ❌ Calling
srv.entities() instead of using srv.entities as getter
- ❌ Not updating validation handlers for
bypass_draft: true default
- ❌ Continuing with Jest instead of migrating to Vitest
- ❌ Using old CAP Java (JDK 17) — must be 21+