CDS pluginCDS plugintypeInstalls into a CAP project and extends the runtime. CAP loads it through cds.requires or the plugin hook.See every one →What this type is →independently maintainedindependently maintainedoriginPublished by one person or a small company outside SAP. Says nothing about quality; the readings say that.See every one →

cds-caching

A caching plugin for CAP covering queries, requests, function results and remote service responses, through a read-through API or @cache annotations, with HCQL and MCP support.

Caches CQN queries, CAP requests and function results through a read-through API or @cache annotations. Stores include memory, SQLite, Redis, PostgreSQL, SAP HANA and the application’s CDS database. Tenant-aware keys are enabled automatically when MTX is detected unless explicitly disabled; user and locale awareness remain configurable. Memory is the default store. The optional store: "cds" mode reuses the application’s database connection; it is distinct from the direct HANA adapter.

Facts

Latestv3.1.1ReleasedLast pushLicenceMIT

Where it sits

Lives in
Provides
CachingCAPCachingcapabilityHolding the result of an expensive read so the next one is cheap. This spans four different things people call caching — HTTP response caching, query result caching, remote service response caching, and application-level memoisation. They are not interchangeable, and picking the wrong one is the usual cause of stale-data bugs in multitenant apps.TelemetryCAPTelemetrycapabilitySeeing what a running service did — traces across handlers and database calls, metrics, and correlation that survives an async boundary.
Flavors
Node.jsfrom its runtime
Requires
@sap/cds≥ 8@sap/cdsartifactRequires @sap/cds >= 8.
Optional
RedisRedisoutside the atlasCache storage through @keyv/redis; other store modes do not require this backend.SQLiteSQLiteoutside the atlasCache storage through @resolid/keyv-sqlite or @keyv/sqlite; other store modes do not require this backend.PostgreSQLPostgreSQLoutside the atlasCache storage through @keyv/postgres; other store modes do not require this backend.SAP HANASAP HANAartifactCache storage through keyv-hana; other store modes do not require this backend.@cap-js/sqlite@cap-js/sqliteartifactThe README requirements table specifies ^1 with cds 8, ^2 with cds 9, and ^3 with cds 10.

Who is behind it

Mike ZaschkaMike ZaschkaPersonMaintains this
In the atlas: maintains 6, contributes to 9, wrote 12
@mikezaschka
maintainerFabianBerrPersonContributes to this
In the atlas: contributes to 1
@FabianBerr
maxi1555PersonContributes to this
In the atlas: maintains 1, contributes to 2, wrote 1
@maxi1555
2 contributors

Before choosing this

Conditions

LicenceSAP Developer License Agreement 3.2 CAP§ 1, 2, 3A cds-plugin is used with SAP CAP materials, or an artifact is explicitly identified as a CAP plugin or application.
  • § 1 License. Productive customer applications are limited to SAP BTP or another SAP-licensed platform, and mass extraction to a non-SAP product is restricted except where solely required for SAP interoperability.
  • § 2 Intellectual Property. The agreement retains SAP's rights in the covered materials and limits making APIs, tools or software available to third parties, while preserving ownership of customer applications subject to SAP's underlying rights.
  • § 3 Artificial Intelligence Training. The agreement prohibits use of the covered materials and customer applications for training artificial-intelligence models or systems.
SAP Developer License Agreement 3.2 CAP →
PracticalFunctional boundary

When user-dependent responses are cached without user-aware or explicit operation keys, or translated responses share keys across locales. These cases require key isolation; locale-aware keys are off by default.

What it declares

Every artifact

Type
CDS plugin
Origin
Independently maintained
Runtime
Node.js

As a CDS plugin

Declared for
>=8
Distributed through
npm

For caching

Caching layer
Read-through results: queries, requests and functions
Freshness control
TTL, tags and optional invalidateOnWrite
Tenant partitioning
Automatic tenant-aware keys in MTX; explicit opt-out available

For telemetry

Signals
TracesMetrics

Tasks this contributes to6Beta

Cache a remote service responseA read that would call out to a remote service on every request is answered from a retained response until it expires.Node.jsCoversresult cache
What it does

cache.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.

All options on the Caching page →
Cache the result of a function callA function the application would otherwise run on every call returns a value retained from an earlier call until it expires.Node.jsCoversresult cache
What it does

Two 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.

All options on the Caching page →
Keep a cached result from reaching the wrong tenant, user or localeA result retained for one tenant, one user or one language is not returned to a request that belongs to another.Node.jsCovers, under conditionskey isolation
What it does

Tenant, 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.

All options on the Caching page →
Refresh cached reads after a writeA read answered from a cache reflects a write to the underlying data within a bound the application sets.Node.jsCoversresult cache
What it does

invalidateOnWrite 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.

All options on the Caching page →
Serve repeated reads of a rarely written entity from a cacheReads of an entity that is read constantly and written rarely are answered inside the application instead of going to the database on every request.Node.jsCoversresult cache
What it does

A @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.

All options on the Caching page →
Share one cache across application instancesSeveral 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.Node.jsCovers, under conditionsresult cache
What it does

The 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.

All options on the Caching page →

Connections12

cds-caching connectionscds-cachingPROVIDES→ provides2provides stated Retains query, request and function results, with expiry and optional entity-write invalidation through @cache annotations. cds-caching — README: https://github.com/mikezaschka/cds-caching/blob/main/README.mdCachingprovides stated Exports distributed traces and metrics for its own cache operations through a dedicated OpenTelemetry integration. cds-caching README: https://github.com/mikezaschka/cds-cachingTelemetryUSED BY← used by1used by derived For response caching. Through: inverted from its requires edge cds-data-federation — Caching Federated Entities: https://mikezaschka.github.io/cds-data/federation/integration/caching.htmlcds-data-federationNEEDS→ available via2available via derived Through: PostgreSQLPostgreSQL on SAP BTP, hyperscaleroptionavailable via derived Through: RedisRedis on SAP BTP, hyperscaler option→ connects to1connects to stated passing cache read and write operations through to the Redis store at runtime cds-caching README: https://github.com/mikezaschka/cds-cachingRedis→ needs1needs stated Requires [@sap/cds](artifact:sap-cds) >= 8. cds-caching — Requirements: https://github.com/mikezaschka/cds-caching/blob/main/README.md@sap/cds→ optionally needs5optionally needs stated If: When the SQLite store is selected. The README requirements table specifies ^1 with cds 8, ^2 with cds 9, and ^3 with cds 10. cds-caching — Requirements: https://github.com/mikezaschka/cds-caching/blob/main/README.md@cap-js/sqliteifoptionally needs stated If: When store: "postgres" is selected. Cache storage through @keyv/postgres; other store modes do not require this backend. cds-caching — Store Types: https://github.com/mikezaschka/cds-caching/blob/main/README.mdPostgreSQLifoptionally needs stated If: When store: "redis" is selected. Cache storage through @keyv/redis; other store modes do not require this backend. cds-caching — Store Types: https://github.com/mikezaschka/cds-caching/blob/main/README.mdRedisifoptionally needs stated If: When store: "hana" is selected. Cache storage through keyv-hana; other store modes do not require this backend. cds-caching — Store Types: https://github.com/mikezaschka/cds-caching/blob/main/README.mdSAP HANAifoptionally needs stated If: When store: "sqlite" is selected. Cache storage through @resolid/keyv-sqlite or @keyv/sqlite; other store modes do not require this backend. cds-caching — Store Types: https://github.com/mikezaschka/cds-caching/blob/main/README.mdSQLiteif

Install

npm add cds-caching

Derived from the package name. No recipe recorded; the README has the configuration.

Learn more3

Readings
  1. CAP just got faster: What's new in cds-caching 1.0Mike Zaschka, SAP Community
  2. Boosting performance in SAP Cloud Application Programming Model (CAP) applications with cds-cachingMike Zaschka, SAP Community
  3. Performance Boost and Caching Strategy for Faster Data Access using "cds-caching" in SAP CAPNaveenChandar, SAP Community
What changed
  1. v3.0

    The statistics and dashboard configuration was removed in favour of metrics and metrics.reuse, and the shape of keys and tags changed, so persistent caches have to be flushed after deploying.

    Makes stale:

    Any configuration snippet using statistics or dashboard, and any advice that assumes a persistent cache survives an upgrade untouched.

3 earlier
  1. v3.0.0

    Cache operations time out after 2000 ms by default instead of waiting indefinitely; operationTimeout raises the limit, and operationTimeout: 0 restores the unbounded behaviour. The dashboard loads UI5 from a CDN instead of bundling it.

    Makes stale:

    The assumption that a slow store only delays a request: from 3.0.0 an operation past the timeout fails.

  2. v2.0

    The metrics configuration changed shape, splitting into metrics and metrics.reuse.

    Makes stale:

    Any configuration snippet setting metrics under the 1.x shape.

  3. v1.0

    The read-through API moved to a runtime namespace: cache.run(), cache.send(), cache.wrap() and cache.exec() were deprecated in favour of cache.rt.*, which returns the cache key and hit or miss metadata alongside the result.

    Makes stale:

    Any code sample calling cache.run() or cache.send() directly. The calls still work but are deprecated, so a tutorial written before this shows the older shape.

Where it sits in your app

Download
Your CAP applicationSAP cloudcds-caching README, checked 2026-10-15: “the `credentials` object is passed through to [`@keyv/redis`](https://keyv.org/docs/storage-adapters/redis/) / [`@redis/client`](https://github.com/redis/node-redis).”connectswhen store: "redis" isselecteddocumentedmay needwhen store: "sqlite" isselecteddocumentedmay needwhen store: "postgres" isselecteddocumentedmay needwhen store: "hana" is selecteddocumentedmay needwhen the SQLite store isselectedRedis, systemRedissystemSQLite, systemSQLitesystemPostgreSQL, systemPostgreSQLsystemcds-caching, modulecds-caching@cap-js/sqlite, module@cap-js/sqliteSAP HANA, service instanceSAP HANA
SAPnot SAP's, or the project's ownstated in the documentunder a condition

README

quoted from mikezaschka/cds-caching under MIT, read
mikezaschka/cds-caching/README.mdOn GitHub

Welcome to cds-caching

npm version monthly downloads

Overview

A caching plugin for the SAP Cloud Application Programming Model (CAP) that improves performance by caching slow remote service calls, complex operations, and queries.

Please also read the introduction blog post: Boosting performance in SAP Cloud Application Programming Model (CAP) applications with cds-caching.

Key Features
  • Read-Through Caching – Transparently cache CQN queries, CAP requests, or function calls
  • Pluggable Storage – In-memory, SQLite, Redis, PostgreSQL, SAP HANA, or CDS database
  • Multi-Tenancy – Automatic tenant isolation for SAP BTP MTX deployments
  • TTL & Tag Support – Time-based expiry and tag-based invalidation
  • Compression – LZ4 or GZIP compression for cached data
  • Metrics & Monitoring – Hit rates, latencies, key-level tracking, and an OData API
  • Annotations – Declarative caching via @cache annotations on entities and functions
Documentation
GuideDescription
Programmatic APIFull API reference for cache operations
Protocol SupportCaching across OData, REST, GraphQL, HCQL, and MCP
Key ManagementKey templates, context awareness, custom keys
SecurityAuthorization, cache key isolation, production checklist
Metrics GuideStatistics, monitoring, and performance tracking
OpenTelemetry IntegrationDistributed tracing and metrics export
OData APIREST endpoints for management and monitoring
DashboardSetup and usage of the monitoring dashboard
Feature ActivationReuse vs own: metrics, API, and dashboard activation
Deployment GuideSAP BTP deployment for Redis, PostgreSQL, HANA, CDS
MTX Hybrid TestManual BTP trial checklist for issue #18 / MTX
Migration GuideUpgrading to 3.0 and earlier releases
Example ApplicationSample app with caching patterns
Federation IntegrationUsing cds-caching with cds-data

Getting Started

Installation
npm install cds-caching
Requirements
DependencySupported versions
SAP CAP (@sap/cds)>= 8 (including cds 9 and cds 10)
Node.js>= 22 (cds 10 requires Node 22+, v24 recommended)
@cap-js/sqlite (SQLite store)^1 on cds 8, ^2 on cds 9, ^3 on cds 10

The plugin runtime supports cds 8, cds 9, and cds 10. When running on cds 10, use Node.js 22 or higher and @cap-js/sqlite ^3.

Minimal Configuration
{
  "cds": {
    "requires": {
      "caching": {
        "impl": "cds-caching"
      }
    }
  }
}

This uses the in-memory store — no additional setup needed for development.

Upgrading to 3.0? See Upgrading to 3.0 — flush persistent caches after deploy; keys and tags change shape. From 1.x, also see Upgrading to 2.0 for the metrics / metrics.reuse config shape.

Data Model

The plugin ships CDS entity definitions for database-backed features. These load conditionally based on your configuration — no manual model property needed.

Full guide: Feature Activation — decision tree, BTP/MTX guidance, and rules for avoiding duplicate model loading.

OptionEntities loadedPurpose
"metrics": { "enabled": true, … }Caches, Metrics, KeyMetricsMetrics persistence (skipped if API loaded via reuse or using)
"store": "cds"CacheStoreCDS-backed cache storage
metrics.reuse.api or using … index.cdsCachingApiService + metrics entitiesOData API (/odata/v4/caching-api/)
metrics.reuse.dashboardSame as reuse API + UI at /caching-dashboardPackage reuse (see reuse & compose)
None of the aboveNothingExternal stores only; basic caching still works

Do not combine metrics.reuse.* with manual using … index.cds or cds add caching-metrics for the same concern — see the Feature Activation guide.

The auto-loading injects CDS files into cds.env.roots at plugin load time, before CAP compiles the model. Run cds deploy after enabling database features.

Basic Usage
const cache = await cds.connect.to("caching")

// Key-value operations
await cache.set("bp:1000001", businessPartnerData, { ttl: 60000 })
const data = await cache.get("bp:1000001")

// Read-through caching for CQN queries
const { result } = await cache.rt.run(query, db, { ttl: 30000 })

// Read-through caching for remote services
const { result } = await cache.rt.send(request, remoteService, { ttl: 10000 })

// Function caching
const cachedFn = cache.rt.wrap("expensive-op", expensiveFunction, { ttl: 3600 })
const { result } = await cachedFn("param1")
Annotation-Based Caching
service MyService {
  @cache: { ttl: 10000 }
  entity Products as projection on db.Products;

  @cache: { ttl: 10000, invalidateOnWrite: true }
  entity Orders as projection on db.Orders;

  @cache: { ttl: 60000 }
  function getRecommendations() returns array of Products;
}

When invalidateOnWrite is set, the cache for that entity is automatically cleared after any CREATE, UPDATE, or DELETE operation, so subsequent reads always return fresh data.

Annotations are protocol-agnostic: cds-caching binds at the CAP service-handler level, so a single @cache annotation applies whether the request arrives via OData, REST, GraphQL, HCQL, or the new MCP protocol adapter — no protocol-specific configuration required. MCP is read-only, so its reads are cached while writes over other protocols still invalidate the shared entries. See the Protocol Support guide for details.

Configuration

Store Types
StoreConfigUse CaseAdapter Package
In-Memory"memory"Development, small-scaleBuilt-in
SQLite"sqlite"Medium-size, single instance@resolid/keyv-sqlite or @keyv/sqlite
Redis"redis"Production, distributed@keyv/redis
PostgreSQL"postgres"Production, when Redis unavailable@keyv/postgres
CDS Database"cds"Production, HANA, multi-tenantNone (uses app's DB)
SAP HANA"hana"Direct HANA connectionkeyv-hana

Recommendation: Use store: 'cds' for CAP applications on SAP HANA — it reuses your app's DB connection, requires no extra packages, and supports multi-tenancy automatically. Use store: 'redis' for best performance in distributed setups.

Full Configuration Options
{
  "cds": {
    "requires": {
      "caching": {
        "impl": "cds-caching",
        "namespace": "caching",
        "store": "redis",
        "compression": "lz4",
        "throwOnErrors": false,
        "transactionalOperations": false,
        "credentials": { },
        "metrics": {
          "enabled": true,
          "persistenceInterval": 60000,
          "reuse": {
            "api": false,
            "dashboard": false
          }
        },
        "keyManagement": {
          "isUserAware": false,
          "isTenantAware": false,
          "isLocaleAware": false
        }
      }
    }
  }
}
OptionDefaultDescription
store"memory"Storage backend (memory, sqlite, redis, postgres, hana, cds)
namespaceservice nameKey prefix for store isolation
compressionnone"lz4" or "gzip"
throwOnErrorsfalseWhether basic operations throw on cache errors
operationTimeout2000Milliseconds a single cache operation may take before it counts as a failure; 0 removes the bound (docs)
transactionalOperationsfalseIsolate basic ops in dedicated cache transactions
metricsnoneMetrics collection and persistence (see Feature Activation)
metrics.enabledfalseEnable metrics collection
metrics.persistenceInterval60000Interval (ms) for persisting hourly stats to the database
metrics.reuse.apifalseRegister CachingApiService from the plugin package (alternative: using … index.cds)
metrics.reuse.dashboardfalseServe the UI from the plugin (alternative: cds add caching-metrics)
metrics.ui5UrlSAPUI5 CDN, pinnedUI5 runtime for the served dashboard; set this to serve UI5 yourself (docs)
encryption.keynone32-byte key (base64 or hex) enabling AES-256-GCM encryption of cached values (docs)
encryption.enabledfalseRequire encryption without committing the key; startup fails if no key is supplied
encryption.keyEnvnoneName of the environment variable holding the key, for platform-supplied secrets (docs)
statistics / dashboard—Removed in 3.0 — use metrics / metrics.reuse (migration)
keyManagement.isTenantAwarefalse (auto true in MTX)Include tenant in cache keys
keyManagement.isUserAwarefalseInclude user in cache keys
keyManagement.isLocaleAwarefalseInclude locale in cache keys
Environment-Specific Configuration
{
  "cds": {
    "requires": {
      "caching": {
        "impl": "cds-caching",
        "store": "redis",
        "[development]": {
          "credentials": { "host": "localhost", "port": 6379 }
        },
        "[production]": {
          "credentials": { "url": "redis://production-redis:6379" }
        }
      }
    }
  }
}
Redis Connection Tuning

For store: "redis", the credentials object is passed through to @keyv/redis / @redis/client. You can use either a connection URL or explicit socket options:

{
  "cds": {
    "requires": {
      "caching": {
        "impl": "cds-caching",
        "store": "redis",
        "throwOnErrors": false,
        "credentials": {
          "url": "rediss://your-redis:6380",
          "pingInterval": 30000,
          "socket": { "keepAlive": true }
        }
      }
    }
  }
}

Use a redis:// or rediss:// URL, or connect via socket.host / socket.port instead of url.

If you see SocketClosedUnexpectedlyError in the logs every few minutes — common with TLS Redis, load balancers, or firewalls that drop idle connections — add pingInterval (milliseconds). The client sends periodic PING commands to keep the connection alive. Place it at the top level of credentials, not inside socket. TCP keepAlive under socket is enabled by default in @redis/client; pingInterval helps when the network path does not honor it.

With the default throwOnErrors: false, disconnects are logged but the application continues: cache operations fall back to misses and @keyv/redis reconnects automatically. If you set throwOnErrors: true, connection errors surface as thrown errors instead; reconnection still happens in the background either way.

An outage cannot stall requests. Commands are never queued while the connection is down, and every cache operation runs under operationTimeout (2s by default), so an unreachable store degrades to cache misses instead of leaving requests waiting.

For detailed key configuration and deployment instructions, see Key Management and Deployment Guide.

Service Integration

The plugin includes CachingApiService, an OData service for managing caches, browsing entries, and viewing metrics. It powers the dashboard and can be consumed by any OData client.

See Feature Activation for reuse vs own activation, BTP/MTX guidance, and API authorization.

Quick reference:

GoalApproach
Local dev with dashboardmetrics.reuse.api + metrics.reuse.dashboard + metrics.enabled
BTP with HTML5 repocds add caching-metrics + metrics.enabled — no metrics.reuse.dashboard
API only, no UImetrics.reuse.api or using … index.cds + metrics.enabled

The API requires an authenticated user by default. Restrict it to an administrative role with a fully-qualified annotate — do not repeat the using import:

annotate plugin.cds_caching.CachingApiService with @requires: 'CacheAdmin';

See the Security Guide for the production checklist, including cache key isolation for user-filtered data.

Multi-Tenancy (MTX)

cds-caching supports SAP BTP multi-tenant applications using @sap/cds-mtxs. When multitenancy is detected, the plugin automatically:

  • Enables tenant-aware cache keys ({tenant}:{hash})
  • Defers database operations to request-time (avoids startup crashes without tenant context)
  • Partitions in-memory metrics per tenant and persists them via cds.spawn({ tenant }) into that tenant’s HDI
  • Lazily seeds Caches rows on dashboard / CachingApi access (not only READ Caches)
{
  "cds": {
    "requires": {
      "multitenancy": true,
      "caching": {
        "impl": "cds-caching",
        "store": "cds",
        "metrics": {
          "enabled": true,
          "persistenceInterval": 60000
        }
      }
    }
  }
}

With store: 'cds', each tenant's cache data lives in its own HDI container — fully isolated by CAP's Service Manager. On HANA, cds build emits CacheStore and Caches / Metrics / KeyMetrics .hdbtable artifacts when metrics or the Caching API are enabled.

Alternatively, use store: 'redis' for shared Redis with automatic tenant-prefixed keys:

{
  "cds": {
    "requires": {
      "multitenancy": true,
      "caching": {
        "impl": "cds-caching",
        "store": "redis",
        "credentials": { "socket": { "host": "localhost", "port": 6379 } }
      }
    }
  }
}

isTenantAware is automatically set to true in MTX mode. Set "isTenantAware": false in keyManagement to explicitly opt out.

For MTX production setup (dashboard, API authorization, store: 'cds'), see the Feature Activation Guide — Multi-tenancy (MTX). To verify against a BTP trial in hybrid mode, see MTX Hybrid Test.

Usage Patterns

Deprecation Notice: cache.run(), cache.send(), cache.wrap(), cache.exec() are deprecated since v1.0. Use cache.rt.run(), cache.rt.send(), cache.rt.wrap(), cache.rt.exec() instead. See Migration Guide.

Read-Through Query Caching
const { result } = await cache.rt.run(
  SELECT.from(BusinessPartners).where({ type: '2' }), 
  db, 
  { ttl: 30000 }
)
Read-Through Remote Service Caching
this.on('READ', BusinessPartners, async (req, next) => {
  const bupa = await cds.connect.to('API_BUSINESS_PARTNER')
  const { result } = await cache.rt.run(req, bupa, { ttl: 30000 })
  return result
})
ApplicationService Caching with prepend
this.prepend(() => {
  this.on('READ', MyEntity, async (req, next) => {
    const cache = await cds.connect.to("caching")
    const { result } = await cache.rt.run(req, next)
    return result
  })
})
Function Caching
// Wrap: create a cached version of a function
const cachedFn = cache.rt.wrap("bp-data", fetchBPData, { ttl: 3600, tags: ['bp'] })
const { result } = await cachedFn("1000001", true)

// Exec: immediate one-off execution with caching
const { result } = await cache.rt.exec("product", fetchProduct, ["1000001"], { ttl: 3600 })
Cache Invalidation
// Time-based (TTL)
await cache.set("key", value, { ttl: 60000 })

// Key-based
await cache.delete("bp:1000001")

// Tag-based
await cache.set("bp:1000001", data, { tags: [{ value: "bp-list" }] })
await cache.set("bp:1000002", data, { tags: [{ value: "bp-list" }] })
await cache.deleteByTag("bp-list")

// Dynamic tags from data
await cache.set("bp-list", bpArray, { 
  tags: [{ data: "businessPartner", prefix: "bp-" }] 
})
Automatic Invalidation on Write

For annotation-based entity caching, use invalidateOnWrite to automatically clear all cached queries for an entity whenever its data changes:

@cache: { ttl: 10000, invalidateOnWrite: true }
entity CachedProducts as projection on db.Products;

This registers after handlers for CREATE, UPDATE, and DELETE that call deleteByTag with an entity-level tag. All cached variants (filtered, sorted, paginated, single-entity) are invalidated at once.

For more usage patterns, error handling details, and TypeScript support, see Programmatic API.

Statistics & Monitoring

To persist metrics to the database, add a metrics block. See the Feature Activation Guide.

{
  "cds": {
    "requires": {
      "caching": {
        "impl": "cds-caching",
        "store": "redis",
        "metrics": {
          "enabled": true,
          "persistenceInterval": 60000
        }
      }
    }
  }
}

You can also enable metrics at runtime:

const cache = await cds.connect.to("caching")
await cache.setMetricsEnabled(true)
await cache.setKeyMetricsEnabled(true)

const stats = await cache.getCurrentMetrics()

To add the monitoring dashboard, use metrics.reuse.dashboard for local reuse, or cds add caching-metrics for BTP. See the Feature Activation Guide and Dashboard Guide.

Cache Dashboard

See the full Metrics Guide →

API Reference

APIDescription
Programmatic APIJavaScript methods for cache operations
OData APIREST endpoints for monitoring and management

cds-data provides composable CAP plugins for federation, replication, and materialization. Use cds-caching as the optional peer for cache.strategy: 'response' on @federation.delegate / @federation.replicate views — see Federation Integration.

Contributing

Contributions are welcome! Please submit pull requests to the repository.

Dashboard UI sources live in app/dashboard-src/. From the repo root, use npm run start:dashboard (with cds watch in examples/app) for TypeScript development, and npm run build:dashboard to regenerate the pre-built bundle in app/dashboard/.

License

This project is licensed under the MIT License - see the LICENSE file for details.

MIT, read

History

Latest

v3.1.1

Fixes 1

Notes
Bug Fixes
  • dashboard: align API URI with CachingApiService and bump UI5 LTS (d1c76b6), closes #32
  1. v3.1.0

    Features 1

    Notes
    Features
    • metrics: add opt-in TagMetrics for per-tag hit ratios (f9922c5)
  2. v3.0.1

    Fixes 3, Docs 1

    Notes
    Bug Fixes
    • dashboard: tidy the reuse dashboard manifest (f993b89), closes #32
    • metrics: sanitize Infinity values before writing KeyMetrics (a2c54fb), closes #33
    • metrics: guard against Infinity when uptimeMs is 0 in hourly stats (e6c2e6d), closes #35
    Documentation
    • point the MTX hybrid checklist at cds-caching 3.0 from npm (ffafafe)
  3. v3.0.0dated in the atlas

    Breaking 5, Features 3, Fixes 10

    Notes
    ⚠ BREAKING CHANGES
    • config: reject removed v1 statistics and dashboard keys
    • resilience: Cache operations now fail after 2000ms rather than waiting indefinitely. A store that is slow but healthy under peak load may need a higher operationTimeout, and operationTimeout: 0 restores the old unbounded behavior.

    Co-authored-by: Cursor cursoragent@cursor.com

    • dashboard: bootstrap UI5 from a CDN instead of bundling it
    • keys: hash cache keys and tags with SHA-256
    • keys: derive cache keys from the effective query
    Features
    • dashboard: bootstrap UI5 from a CDN instead of bundling it (1803e23), closes #29
    • encryption: optionally encrypt cached values at rest (9c73616)
    • keys: hash cache keys and tags with SHA-256 (0fbe498)
    Bug Fixes
    • build: emit CachingApiService hdbviews for HANA OData reads (1e5e004)
    • build: emit CachingApiService views via official HANA build (95b7fab)
    • config: reject removed v1 statistics and dashboard keys (9540454)
    • encryption: make the documented ways of supplying a key actually work (6b12ffe)
    • keys: derive cache keys from the effective query (0275f96)
    • mtx: complete tenant metrics, HANA stats tables, and lazy Caches seed (a413e17), closes #18
    • mtx: map CachingApiService OData reads to base HANA tables (9dfd053)
    • resilience: bound cache operations so an unreachable store cannot stall requests (4b7d4ed)
    • tags: use the bare content hash in CQL tag templates (3b46949)
    • update npm badge link in README.md (1b76afe)
  4. v2.1.0

    Features 5, Fixes 3

    Notes
    Features
    • api: bound getEntries and setEntry (4dd6ee3)
    • api: require an authenticated user for CachingApiService (0e399be)
    • api: resolve cache names against an allow-list (2b26179)
    • cache: make the x-sap-cap-cache-key header opt-in (4f8d7b6)
    • config: warn when keyManagement sits outside cds.requires (dac9084)
    Bug Fixes
    • build: stop logging cds.env.requires during cds build (1536143)
    • dashboard: serve the reuse dashboard behind CAP's auth (7f5feec)
    • metrics: redact credentials and bound fields in KeyMetrics (9cb22ba)
  5. v2.0.2

    Fixes 1

    Notes
    Bug Fixes
    • prevent NaN on HANA metrics hourly-stats UPDATE (#27) (fd207cd)
  6. v2.0.1

  7. v2.0.0

    Features 6, Fixes 4

    Notes
    Features
    • add config normalizer for metrics v2 and legacy compatibility (ec77573)
    • add plugin roots resolver for metrics reuse activation (593d517)
    • dashboard: add key metric detail view and table filters (020cbf0)
    • expand cds add caching-dashboard with --source scaffold (52b96f0)
    • serve bundled dashboard when dashboard: true (1ad7fae)
    • update cds add scaffold for HTML5 repo zip deploy (e62f773)
    Bug Fixes
    • hash CQN when URL has no query string (54ecf48)
    • normalize dashboard i18n unicode escapes (7253ae0)
    • serve dashboard static files with express.static (6cf99ab)
    • treat HCQL POST SELECT as cacheable read (9ff1f90)
  8. v1.3.2

    Features 4, Fixes 1

    Notes
    Features
    • enhance caching plugin with runtime model integration (ce0666d)
    • implement automatic cache invalidation on write (6f5f9d4)
    • integrate i18n support in dashboard (c480648)
    • refactor caching plugin for improved HANA build integration (dacc012)
    Bug Fixes
    • add main export for caching service in cds-plugin (c1cf253)
  9. v1.3.1

    Features 2

    Notes
    Features
    • enhance cache clear functionality and update documentation (7e92948)
    • enhance KeyManager to include HTTP URL in cache key generation (1b1ed6b)
  10. v1.3.0

    Features 7, Fixes 4

    Notes
    Features
    • add caching dashboard integration and update documentation (982d86f)
    • enhance caching plugin and update dependencies (994aa21)
    • enhance caching plugin with auto-loading of entity models and improved statistics handling (ac77959)
    • enhance dashboard formatter and update resource links (f015e7c)
    • include hana and postgres support (096e9c7)
    • integrate OpenTelemetry for enhanced caching metrics (4c20f60)
    • update caching plugin for multi-tenancy support and enhance documentation (a15d74b)
    Bug Fixes
    • apply all PR review feedback for telemetry integration (91b49cd)
    • apply PR review feedback - remove credential leak, fix hasTask, per-tenant init, docs updates (f817865)
    • only create hdbtable for hana based caching (c8abec1)
    • remove redundant logging and add table build logging in caching plugin (7e560ec)
  11. v1.2.1

  12. v1.2.0

    Fixes 2

    Notes
    Bug Fixes
    • changed db.entities to cds.entities - for future use (562d5c4)
    • remove console.log statement fixes #14 (cdd6893)
  13. v1.1.0

285downloads per week, npm
Weekly downloads for cds-caching26 complete calendar weeks from 2026-04-20 to 2026-10-18; the latest total is 285.20 Apr – 26 Apr: 44827 Apr – 3 May: 4494 May – 10 May: 33111 May – 17 May: 5,39418 May – 24 May: 36125 May – 31 May: 2641 Jun – 7 Jun: 3148 Jun – 14 Jun: 51615 Jun – 21 Jun: 25222 Jun – 28 Jun: 43629 Jun – 5 Jul: 6686 Jul – 12 Jul: 47213 Jul – 19 Jul: 75620 Jul – 26 Jul: 53627 Jul – 2 Aug: 8303 Aug – 9 Aug: 45810 Aug – 16 Aug: 55117 Aug – 23 Aug: 68524 Aug – 30 Aug: 52431 Aug – 6 Sept: 3757 Sept – 13 Sept: 25314 Sept – 20 Sept: 83021 Sept – 27 Sept: 67428 Sept – 4 Oct: 5985 Oct – 11 Oct: 47912 Oct – 18 Oct: 285

Others providing23

Caching
  1. Redis on SAP BTP, hyperscaler optionManaged Redis from the hyperscaler via a BTP service bindingfrom BTP/BAIP
  2. @cap-js-community/commonSix CAP features in one package, from replication cache to rate limitsfrom CAP
  3. ABAP-CACHE-BOXGenerates singleton ABAP cache classes from a macro callfrom ABAP
  4. cds-data-federationData federation for CAP via delegation, caching and replicationfrom CAP
  5. @sap/cdsCAP Node.js runtimefrom CAP
Telemetry
  1. abap-metrics-providerExposes ABAP stack metrics to a monitoring toolfrom ABAP
  2. admin-cockpitUsage, error and response-time monitor for abap2UI5from ABAP
  3. SAP Cloud LoggingOpenSearch-based store for logs, metrics and tracesfrom BTP/BAIP
  4. Agent Activation for Dynatrace Service for SAP BTPInjects the Dynatrace agent into Java applications on SAP BTPfrom BTP/BAIP
  5. SAP Monitoring Service for SAP BTPMetrics, availability checks and alerts for apps in Neo regionsfrom BTP/BAIP
  6. com.sap.cds:cds-services-bomMaven bill of materials pinning CAP Java module versionsfrom CAP
  7. @cap-js-community/business-metricsBusiness-level metrics from CDS annotations via @cap-js/telemetryfrom CAP
  8. @cap-js/telemetryOpenTelemetry instrumentation for CAP servicesfrom CAP
  9. cap-mcp-guardPolicy enforcement and field masking for MCP-enabled CAP appsfrom CAP
  10. abap-opentelemetryOTLP serialisation of traces, metrics and logs in ABAPfrom ABAP
  11. abap-prometheusPrometheus client for ABAP, installed with abapGitfrom ABAP
  12. @sanjay-sde/cap-js-log-controlCAP plugin controlling CDS logger and OpenTelemetry log verbosityfrom CAP
  13. @sap/e2e-traceSAP Passport handling for Node.js componentsfrom BTP/BAIP
  14. @sap-ux/telemetryLibrary for sending usage telemetry datafrom CAP
  15. @saptools/cf-metricsRead-only query tool for metrics in SAP Cloud Loggingfrom BTP/BAIP
  16. @saptools/cf-otelRead-only query tool for OpenTelemetry spans in SAP Cloud Loggingfrom BTP/BAIP
  17. cap-ui-telemetryUI5 frontend performance and error capture for CAPfrom CAP
  18. opentelemetry-cdsOpenTelemetry support for the CDS Node.js runtimefrom CAP

Details

Sources5
npm registrydiscovered herechecked
The maintainer, claiming itdiscovered herechecked
npm registry, cds-cachingversion, releases, installschecked
github.com/git+https://github.com/mikezaschka/cds-caching.gittree, pushes, contributors, CIchecked
README.mdquoted, and what the entry declareschecked

Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.

Compatibility and provenance
runtimesnode
declared for>=8
latestv3.1.1
first release
releases and cadence22, ~6d median
discovered vianpm registry, The maintainer, claiming it
first seen in the atlas
ecosystem and domaincap, data-and-persistence
Contributors2

From the repository’s contributor list, .

History in the atlas4
  1. Removed the unconditional compat.multitenancy flag; recorded the MTX default and user/locale conditions in prose and sourced caching facets
  2. Required CAP runtime and conditional cache-store relationships; default memory and CDS reuse clarified
  3. Withheld verdicts retired with the rings. Nothing is recused from: facts about an entry are facts whoever maintains it, and a starting-point is answered by description.to_build_on_it.
  4. First seen.
For your agent