CapabilityData & PersistenceNode.js, read from its artifacts

Caching

Caching in CAP can mean HTTP response validation, retaining the result of a query or function, or querying a replicated copy of service data. The core, application plugins and a backing store answer different parts of that concern. HTTP response caching, query-result caching, remote-service response caching and application-level memoisation are different choices; stale-data behaviour and tenant isolation need to be considered for the chosen layer.

Showing artifacts, examples and content with confirmed Node.js applicability. View All CAP

Overview

SAP SHIPS
@sap/cds

Supports ETag-based conditional HTTP reads for annotated entities in the CAP Node.js runtime.

Sourcecapire — Generic Service Providerschecked

A Node.js coverage assessment has not been written. View all flavors

THE COMMUNITY ADDS
@cap-js-community/common

Replicates a service into tenant-aware SQLite for querying with the original service’s queries; @cds.replicate selects entities and exposes TTL, preload and static replication options.

cds-caching

Retains query, request and function results, with expiry and optional entity-write invalidation through @cache annotations.

Sourcecds-caching — READMEchecked
cds-data-federation

Caches federated responses through cds-caching, or retains entity snapshots through cds-data-pipeline. Writable delegates require manual invalidation or a shorter TTL.

A Node.js coverage assessment has not been written. View all flavors

Artifacts5

5 of 5 artifacts
ArtifactSignals
CDS plugins2
cds-cachingCAP caching plugin for query results and remote service responses
Signals
Functional boundary
cds-data-federationData federation for CAP via delegation, caching and replication
Signals
none
Packages2
@cap-js-community/commonSix CAP features in one package, from replication cache to rate limits
Signals
Functional boundary
@sap/cdsCAP Node.js runtime
Signals
none
Services1
Redis on SAP BTP, hyperscaler optionManaged Redis from the hyperscaler via a BTP service binding
Signals
none

Tasks8Beta

CoversCovers, under conditionsStated not supportedAssessed, not knownNot assessed
Cache a remote service response1 covers, 1 under conditions, 1 not known

A read that would call out to a remote service on every request is answered from a retained response until it expires.

Covers a response from a service the application calls out to. Retaining the result of a local query is a separate task, and so is copying the remote data into a local database and querying that.

Coverscds-cachingcache.rt.send takes the request and the remote service and returns the retained response with the ttl the call states. The call is written where the application would otherwise send to the service.

Remaining work: Choose the ttl and call the cache instead of the service. The plugin documents the call, not which reads are worth retaining.

Open artifact →

Covers, under conditionscds-data-federationOn a delegated entity the response strategy routes the federated read through cds-caching, so the retaining is declared on the consumption view rather than written into a handler. The entity strategy answers a different shape of the same wish: it stores a snapshot of the remote projection in secondary SQLite and serves reads from there until the ttl runs out.

Conditions: cache.strategy is left at its default of response cds-caching is installed, which the page names as an optional peer dependency

Remaining work: Install the peer dependency and annotate the view. The strategy selects a cache, it is not a second one; the entity strategy brings cds-data-pipeline and @cap-js/sqlite with it.

Open artifact →

Assessed, not known@sap/cdsWhether the CAP Node.js runtime retains a remote service response is not established here. Capire's CAP-level Service Integration guide, read on 2026-09-19, covers importing an API, integrating the model and writing the integration logic, and does not mention caching.

Remaining work: Read the remote services and destinations documentation on capire before treating this as settled. Absence from the integration guide is not a statement that the runtime does nothing.

Open artifact →

Cache the result of a function call1 covers, 1 not known

A function the application would otherwise run on every call returns a value retained from an earlier call until it expires.

Covers retaining what a function returns, under a key that carries the arguments it was called with. Retaining the result of a query and retaining a response from a remote service are separate tasks, and so is where the retained value is kept.

Coverscds-cachingTwo routes to the same outcome. A @cache annotation on a function in the CDS model retains what it returns for the ttl it states, so the decision sits on the declaration. In code, cache.rt.wrap takes a name and the function and hands back a cached version of it, and cache.rt.exec runs a function once with its arguments and retains what came back. The arguments are part of the generated key, so a call with different arguments is held separately.

Remaining work: Name the function and choose the ttl. Whether a function returns the same value for the same arguments stays the application's to decide: the pages read here document the key and the expiry, not which functions are worth retaining or safe to retain.

Open artifact →

Assessed, not known@sap/cdsWhether the CAP Node.js runtime retains what a function returns is not established here. No capire page documenting a result cache for a function or an action was located for this assessment.

Remaining work: Read the Node.js runtime and performance documentation on capire before treating this as settled. Nothing read here states that the runtime does this, and nothing read here states that it does not.

Open artifact →

Keep a cached result from reaching the wrong tenant, user or locale2 under conditions

A result retained for one tenant, one user or one language is not returned to a request that belongs to another.

Covers the key a retained entry is held under and where the store keeps it. Tenant isolation of the application's own data, and the subscription mechanics themselves, belong to multitenancy and are assessed there. Nothing here establishes that a leak was observed or ruled out in any application.

Covers, under conditions@cap-js-community/commonThe replica is held in a tenant-aware SQLite database, so each tenant queries its own copy. One annotation opts out of that: static replication is stated as non-tenant aware, which is the arrangement for rows that are the same for everyone.

Conditions: The entity is not annotated for static replication, which the README states is not tenant aware

Remaining work: Check every entity annotated for static replication for whether its rows really are the same for all tenants. User and locale are not dimensions this section names at all.

Open artifact →

Covers, under conditionscds-cachingTenant, user and locale are three separate dimensions of the cache key with three different defaults. Tenant awareness turns itself on when multitenancy is detected. User awareness is the application's to set, because a result a handler filters after the query has run carries the same key for every caller. Locale is off, so responses in different languages share one entry until it is switched on. Where the entries sit follows the store: with the cds store each tenant's cache data is held in that tenant's own HDI container.

Conditions: Multitenancy is detected, which is what turns tenant-aware keys on, and the opt-out is not set User awareness is set for caches whose responses vary per user without the query varying Locale awareness is set for caches holding translated texts

Remaining work: Decide per cache which dimensions belong in the key and set the ones that do not default. The plugin documents the switches, not which of an application's responses vary by user or language.

Open artifact →

Refresh cached reads after a write2 covers, 1 no

A read answered from a cache reflects a write to the underlying data within a bound the application sets.

Covers what clears or ages out a retained result. Which reads are retained, and where they are kept, are separate tasks.

Covers@cap-js-community/commonThe replica ages out on a time to live given in milliseconds, and the same annotation block carries auto and preload for when the copy is made. Time is the bound this section states.

Remaining work: Set the ttl per entity. Whether a write through the replicated service clears its copy is not stated in the section read here, so the ttl is the only bound this assessment records.

Open artifact →

Coverscds-cachinginvalidateOnWrite clears the cached queries for an entity when its data changes, registered as after handlers for CREATE, UPDATE and DELETE. Tags are the other route: keys set under a tag are cleared together by deleteByTag, which is how a write can clear a result assembled from several keys.

Remaining work: Set the flag per entity, or assign tags and call deleteByTag from the handler that writes. A write that reaches the data by another route is not covered by either.

Open artifact →

Stated not supportedcds-data-federationAutomatic clearing on a write. A write through a writable delegate does not clear the cache under either strategy, and the documentation records that as a stated behaviour with the alternative named.

Remaining work: Clear the entry from the write path, or shorten the ttl so the window is the staleness the application accepts.

Open artifact →

Serve repeated reads of a rarely written entity from a cache2 covers, 1 not known

Reads of an entity that is read constantly and written rarely are answered inside the application instead of going to the database on every request.

Covers retaining the result of a read. Keeping it fresh after a write is a separate task, and so is where the retained result is kept.

Covers@cap-js-community/commonAnswers the same outcome by a different mechanism: it holds a copy of a service in SQLite and runs the original query against the copy, so the read shape in the application does not change. The README gives the db service as its example.

Remaining work: Install @cap-js/sqlite as a dependency rather than a development dependency, and annotate the entities to replicate.

Open artifact →

Coverscds-cachingA @cache annotation on a service entity retains the results of reads on it for the ttl it states, and it sits on the projection rather than in a handler. Where the decision belongs in code instead, cache.rt.run takes the query and the service and returns the result with the ttl the call states.

Remaining work: Decide the ttl entity by entity. The annotation is per projection, so each one is its own decision, and nothing picks the entities worth retaining.

Open artifact →

Assessed, not known@sap/cdsWhether the CAP Node.js runtime holds a query result between requests is not established by the pages read for this assessment. Capire's generic service providers page documents ETag validation, which answers a conditional request rather than retaining a result, and the service integration guide read on 2026-09-19 does not mention caching at all.

Remaining work: Read the CAP Node.js databases and performance documentation before treating this as settled. Two guessed capire URLs for a performance guide returned 404 on 2026-09-19, so the page that would answer it was not located.

Open artifact →

Share one cache across application instances1 covers, 1 under conditions

Several instances of the same application read and write one cache, so a result retained while serving one request answers a later request routed to a different instance.

Covers where a retained result is kept. What is retained, and when it expires, are separate tasks. Whether a subaccount may provision a given service plan is a project question and is not assessed here.

CoversRedis on SAP BTP, hyperscaler optionThe instance an application binds when the redis store is configured. The plugin's deployment guide provisions service redis-cache in the mta descriptor and tags the instance cds-caching; SAP's service metadata records the plans the service offers, from a free plan for non-productive development to a premium one.

Remaining work: Provision an instance on a plan the subaccount is entitled to and bind it. Which plans a given subaccount may use is a project question, not a documented property of either the service or the plugin.

Open artifact →

Covers, under conditionscds-cachingThe store is configuration rather than code. The table names memory for development and small scale, sqlite for a single instance, redis for production and distributed use, postgres, a direct hana connection, and a cds store that uses the application's own database. Under multitenancy the README states what each of the two production shapes does with tenants: the cds store puts each tenant's cache data in its own HDI container, and the redis store prefixes keys with the tenant.

Conditions: A store other than the default memory store is configured The adapter package the store table names for that store is installed

Remaining work: Set the store, install its adapter package and bind the backing service. Memory is what is configured until then.

Open artifact →

Skip resending a record the client already has1 covers

A client that re-reads an entity it has already fetched gets 304 and no body back when the record has not changed since.

Covers a conditional read over HTTP on a served entity. Retaining a query, request or function result inside the application is a separate task, and so is telling a client how long it may reuse what it has without asking again.

Covers@sap/cdsA read carrying If-None-Match is answered with 304 and no body while the annotated element still matches. Capire's example is a GET on Employees/111 with the previous timestamp in the header.

Remaining work: Annotate an element with @odata.etag. Capire annotates modifiedAt from the managed aspect, which changes on each modification, and the client has to send back what it received.

Open artifact →

Tell a client how long a served file stays fresh1 no

A client that has fetched a file served by the application keeps using it for a stated number of seconds without asking the application again.

Covers the freshness window the application sends with a response. Answering a conditional request with 304, which still costs a round trip, is a separate task, and so is retaining a result inside the application.

Stated not supported@sap/cdsCapire scopes the Cache Control feature to the Java runtime, so the same annotation is not documented as doing anything on Node.js.

Remaining work: Set the header from the application's own code, or take one of the other mechanisms this capability records. The page does not state what a Node.js runtime does with @http.CacheControl when the annotation is in the model.

Open artifact →

Content5

Group by
Piece, what it offers
Performance Boost and Caching Strategy for Faster Data Access using "cds-caching" in SAP CAP
SAP Community, NaveenChandar, BlogThe reasoningA recipeRunnable code
New majors
Performance Boost and Caching Strategy for Faster Data Access using "cds-caching" in SAP CAP
SAP Community, NaveenChandar, BlogThe reasoningA recipeRunnable code
New majors
CAP just got faster: What's new in cds-caching 1.0
SAP Community, Mike Zaschka, BlogThe reasoningA reference
Version drift
Boosting performance in SAP Cloud Application Programming Model (CAP) applications with cds-caching
SAP Community, Mike Zaschka, BlogThe reasoningA recipe
Version drift
Federating, Replicating, and Caching Remote Data in CAP — Part 2
SAP Community, Mike Zaschka, part 2 of 2, BlogThe reasoningA recipeRunnable code
The Full Picture: Federating, Replicating, and Caching Remote Data in CAP — Part 1
SAP Community, Mike Zaschka, part 1 of 2, BlogThe reasoning

Details

Coverage
statecore and community, CAP, Node.js, derived
also inBTP/BAIP, ABAP
Comparison properties3

These are the questions used to compare what the artifacts do. Values come from their documentation and may apply to a particular ecosystem or runtime. Each recorded value in the comparison opens its statement and sources.

Caching layerFreshness controlTenant partitioning
For your agent