The Chart Templates Behind Your CAP Kyma Deployment
When you run cds add kyma on a CAP project, cds-dk generates a Helm umbrella chart whose Chart.yaml declares a list of dependencies. If you've opened that file, you've seen something like this:
apiVersion: v2
name: bookshop
description: A simple CAP project.
type: application
version: 1.0.0
appVersion: 1.0.0
annotations:
app.kubernetes.io/managed-by: cds-dk/helm
dependencies:
- name: web-application
alias: srv
version: ">0.0.0"
- name: service-instance
alias: hana
version: ">0.0.0"
- name: content-deployment
alias: hana-deployer
version: ">0.0.0"
- name: service-instance
alias: xsuaa
version: ">0.0.0"A natural question follows: how many of these chart templates exist, and what can I configure in each? This post answers exactly that, based on inspecting the @sap/cds-dk module itself (v10.x), and gives you the full list of knobs with practical examples (as of July 2026).
Series — SAP BTP Kyma Runtime:
- Preparing Your Environment For SAP BTP Development on Kyma Runtime
- Deploying Your First CAP Application on SAP BTP Kyma Runtime
- Creating BTP Service Instances on SAP BTP Kyma Runtime with the Service Operator
- Binding BTP Service Instances to your CAP Application with Kyma Runtime
- The Chart Templates Behind Your CAP Kyma Deployment (this post)
- Creating roles for your CAP Application on SAP BTP Kyma Runtime
- Using Istio Gateway as Entry Point in SAP BTP Kyma Runtime
Three Chart Templates
Here's the key insight that trips up most developers: no matter how long your dependencies: list is, it is built from only three reusable subcharts (as of July 2026). They ship inside the cds-dk Helm plugin:
@sap/cds-dk/lib/build/plugins/helm/files/subcharts/
├── web-application/ # chart version 2.x
├── service-instance/ # chart version 1.x
└── content-deployment/ # chart version 1.xHere a description of each, and the typical alias you might see in your umbrella chart's Chart.yaml:
Subchart (name) |
What it deploys | Typical alias |
|---|---|---|
web-application |
A runnable workload: Deployment + Service, plus optional APIRule/VirtualService, HPA, RBAC, NetworkPolicy, PodDisruptionBudget and service bindings. |
srv, approuter |
service-instance |
A BTP service instance and binding via the SAP BTP Service Operator (ServiceInstance + ServiceBinding). |
hana, xsuaa, destination, connectivity, html5-apps-repo-host |
content-deployment |
A one-off Job that deploys content (e.g. the HANA table/data deployer). |
hana-deployer |
The name field selects the template; the alias field names the instance. That's why the example at the top has four dependencies but only three distinct names — service-instance appears twice, once aliased as hana and once as xsuaa. You can add as many service-instance entries as you have BTP services to provision.
Not subcharts, but worth knowing: the plugin also carries helpers for
approuter,connectivityandhtml5-repo. These inject aConfigMapinto the umbrella chart's owntemplates/folder — they are not standalone subcharts. The approuter and html5-apps-deployer workloads themselves still run through theweb-applicationchart.
You configure each subchart from the umbrella chart's values.yaml, keyed by the alias. If you're new to how parent charts pass values down to their children, see Helm for Kubernetes — Managing Dependencies.
# values.yaml (umbrella chart)
srv: # -> configures the web-application subchart aliased as "srv"
replicaCount: 2
hana: # -> configures the service-instance subchart aliased as "hana"
serviceOfferingName: hana
servicePlanName: hdi-sharedNow let's break down the knobs for each template.
The "web-application" — Your Runnable Workload
This is the workhorse. It renders a Deployment and a Service, and depending on your values, an APIRule to expose it, an HPA to scale it, RBAC, a NetworkPolicy, and service bindings that mount BTP credentials into the pod.
The Knobs
| Key | Default | Purpose |
|---|---|---|
replicaCount |
1 |
Number of pods in the Deployment. |
port |
8080 |
Container port the app listens on. |
image.repository / image.registry / image.tag |
— | Container image coordinates. |
imagePullPolicy |
— | Always / IfNotPresent / Never. |
command / args |
— | Override the container entrypoint. |
env / envFrom |
{} / [] |
Environment variables (inline, or from Secret/ConfigMap). |
resources.requests / resources.limits |
— | CPU / memory / ephemeral-storage requests & limits. |
additionalVolumes |
[] |
Extra volumes + mounts. |
runAsUser |
— | UID for the container process. |
readOnlyRootFilesystem |
— | Harden the container filesystem. |
expose.enabled |
true |
Whether to create an APIRule and expose the app externally. |
expose.host / expose.hosts |
— | Custom DNS host(s) for inbound traffic. |
expose.gateway |
kyma-system/kyma-gateway |
Istio gateway used for incoming traffic. |
expose.rules |
noAuth on /* |
APIRule access rules (methods, path, CORS policy). |
istio.enabled |
true |
Whether the pod joins the Istio mesh (required for APIRule v2). |
health.liveness / health.readiness |
/healthz |
Probe paths, thresholds and timeouts. |
health.port |
— | Separate port for health probes, if different from port. |
startupTimeoutSeconds |
30 |
Grace window for the app to start before liveness kicks in. |
terminationGracePeriodSeconds |
30 |
SIGTERM grace period. |
hpa.enabled / hpa.minReplicas / hpa.maxReplicas |
false / 1 / 3 |
Horizontal Pod Autoscaler. |
hpa.behavior / hpa.metrics |
— | Custom scaling metrics/behaviour. |
availability.podDisruptionBudget |
maxUnavailable: 10% |
PDB for voluntary disruptions. |
availability.topologySpreadConstraints |
zone + hostname | Spread pods across zones/nodes. |
networkSecurity.enabled |
true |
Generate a NetworkPolicy. |
networkSecurity.ingress / additionalPorts |
[] |
Allowed ingress sources and extra ports. |
rbac.role / rbac.clusterRole / rbac.rules |
{} |
Attach or create RBAC (only one of the three). |
bindings |
see below | BTP service bindings mounted into the pod. |
prometheus.enabled / prometheus.path / prometheus.port |
false / /metrics |
Prometheus scrape annotations. |
otlp.metrics / otlp.traces / otlp.logs |
enabled: true |
OpenTelemetry endpoints (Kyma Telemetry). |
sidecars |
— | Additional containers in the pod (image, env, resources, health). |
nodeSelector / nodeAffinity |
— | Pod scheduling constraints. |
annotations.deployment / annotations.service |
{} |
Extra annotations on the Deployment/Service. |
nameOverride / fullnameOverride |
— | Override generated resource names. |
global.imagePullSecret.name / global.image |
image-pull-secret |
Cluster-wide image pull settings (shared with all subcharts). |
Example — a scalable, bound CAP service
# values.yaml (umbrella chart)
srv:
replicaCount: 2
image:
repository: my-registry/bookshop-srv
tag: "1.0.0"
resources:
requests:
cpu: 200m
memory: 256M
limits:
cpu: 500m
memory: 512M
hpa:
enabled: true
minReplicas: 2
maxReplicas: 5
expose:
enabled: true
rules:
- path: /*
methods: [GET, POST, PUT, PATCH, DELETE]
noAuth: false # require auth via the mesh
bindings:
hana:
serviceInstanceName: hana
xsuaa:
serviceInstanceName: xsuaa
health:
liveness:
path: /health
readiness:
path: /healthThe bindings block is the bridge between this workload and your service-instance dependencies: each entry references a serviceInstanceName and mounts its credentials Secret into the pod. See Creating BTP Service Instances on SAP BTP Kyma Runtime with the Service Operator for how those instances are created.
The "service-instance" — Provisioning BTP Services
This chart is the declarative counterpart to cf create-service. It renders a ServiceInstance and (optionally) a ServiceBinding custom resource for the SAP BTP Service Operator to reconcile.
The Knobs
| Key | Default | Purpose |
|---|---|---|
serviceOfferingName |
— | The BTP service offering (e.g. hana, xsuaa, destination). |
servicePlanName |
— | The plan (e.g. hdi-shared, application, lite). |
externalName |
— | Name of the instance as it appears in BTP. |
btpAccessCredentialsSecret |
— | Secret holding the subaccount credentials for provisioning. |
customTags |
— | Tags copied into the binding secret under tags. |
parameters |
— | Service-specific provisioning parameters (inline map). |
jsonParameters |
— | Same, provided as a JSON string. |
parametersFrom |
— | Pull parameters from a Secret/ConfigMap key. |
bindings |
see below | One or more ServiceBindings, with rotation policy. |
bindings.defaultProperties.credentialsRotationPolicy |
disabled | Automatic credential rotation (rotationFrequency, rotatedBindingTTL). |
annotations.serviceInstance / annotations.serviceBinding |
{} |
Extra annotations on the CRs. |
nameOverride / fullnameOverride |
— | Override generated resource names. |
Example — an XSUAA instance with parameters
# values.yaml (umbrella chart)
xsuaa:
serviceOfferingName: xsuaa
servicePlanName: application
parameters:
xsappname: bookshop
tenant-mode: dedicated
role-templates:
- name: Viewer
description: View books
bindings:
xsuaa:
credentialsRotationPolicy:
enabled: true
rotationFrequency: "720h" # rotate every 30 days
rotatedBindingTTL: "24h" # keep the old binding for 24hAnd a minimal HANA instance:
hana:
serviceOfferingName: hana
servicePlanName: hdi-sharedThe "content-deployment" — One-Off Jobs
Some BTP scenarios need a task that runs once to push content — the classic example being the HANA HDI deployer, which creates tables and loads initial data. This chart renders a Kubernetes Job (plus a ServiceAccount and any bindings the job needs).
The Knobs
| Key | Default | Purpose |
|---|---|---|
image.repository / image.registry / image.tag |
— | The deployer image to run. |
command / args |
— | Override the job's entrypoint. |
env / envFrom |
{} / [] |
Environment variables for the job. |
resources.requests / resources.limits |
— | CPU / memory / ephemeral-storage. |
bindings |
— | BTP service bindings the job needs (e.g. the HANA instance). |
ttlDaysAfterFinished |
14 |
Auto-clean the Job this many days after it completes. |
serviceAccountName |
— | ServiceAccount for the job pods. |
runAsUser |
— | UID for the container process. |
readOnlyRootFilesystem |
— | Harden the container filesystem. |
nodeSelector / nodeAffinity |
— | Scheduling constraints. |
annotations.job |
{} |
Extra annotations on the Job/pods. |
nameOverride / fullnameOverride |
— | Override generated resource names. |
global.imagePullSecret.name |
image-pull-secret |
Shared image pull settings. |
Example — a HANA deployer job
# values.yaml (umbrella chart)
hana-deployer:
image:
repository: my-registry/bookshop-hana-deployer
tag: "1.0.0"
bindings:
hana:
serviceInstanceName: hana
ttlDaysAfterFinished: 7Putting It All Together
A typical bookshop deployment wires all three templates together — the deployer runs once to set up the database, the service instances provision HANA and XSUAA, and the web-application runs your CAP service bound to both:
# Chart.yaml
dependencies:
- name: web-application
alias: srv
version: ">0.0.0"
- name: service-instance
alias: hana
version: ">0.0.0"
- name: content-deployment
alias: hana-deployer
version: ">0.0.0"
- name: service-instance
alias: xsuaa
version: ">0.0.0"# values.yaml
srv:
image: { repository: my-registry/bookshop-srv, tag: "1.0.0" }
bindings:
hana: { serviceInstanceName: hana }
xsuaa: { serviceInstanceName: xsuaa }
hana:
serviceOfferingName: hana
servicePlanName: hdi-shared
hana-deployer:
image: { repository: my-registry/bookshop-hana-deployer, tag: "1.0.0" }
bindings:
hana: { serviceInstanceName: hana }
xsuaa:
serviceOfferingName: xsuaa
servicePlanName: applicationFinding This For Yourself
Everything here came straight from the module. To inspect the shipped subcharts and their default values on your own machine:
# Locate your cds-dk install
CDS=$(npm root -g)/@sap/cds-dk
# List the three subchart templates
ls "$CDS/lib/build/plugins/helm/files/subcharts"
# Read the default values for any of them
cat "$CDS/lib/build/plugins/helm/files/subcharts/web-application/values.yaml"After cds add kyma and after building the project, the same charts also land in your project's gen/chart/charts/ folder, so you can browse them right next to your code.
Related Reading
- Deploying Your First CAP Application on SAP BTP Kyma Runtime — where the umbrella chart is first generated.
- Creating BTP Service Instances on SAP BTP Kyma Runtime with the Service Operator — the CRs behind the
service-instancechart. - Helm for Kubernetes — Managing Dependencies — how umbrella charts pass values down to subcharts.
- Helm for Kubernetes — Templates and Functions — the Go templating that renders these charts.
- SAP CAP — Deploy to Kyma — the official capire guide for
cds add helm.
