{"ref":"capability:transaction-management","page":"/capabilities/transaction-management","json":"/capabilities/transaction-management.json","generated":"2026-10-26","drafted_with_ai":true,"entity":{"id":"transaction-management","name":"Transaction management","domain":"data-and-persistence","ecosystems":["cap"],"universal":true,"description":"Deciding where a unit of work begins and ends, and what travels with it: the database transaction that commits or rolls back around a request, the user, tenant and locale that every nested call inherits, and the work that must run outside the request in a transaction of its own. Distinct from [concurrency control](capability:concurrency-control), which is two writers on one record, and from [async processing](capability:async-processing), which is work that survives the commit.","short":"Deciding where a unit of work begins and ends","core_coverage":{"state":"core-only","assessed_at":"2026-09-27","what_core_does":"Built in: a service call starts a root transaction or joins the one already running and commits or rolls back at the end, so a request in an event handler is always inside one; `cds.tx()` demarcates one by hand where two queries must share it outside a handler, and a nested transaction commits with its root. `cds.context` carries the user, the tenant, the locale and the HTTP request through every nested call, and a new root inherits what its context argument does not override. `cds.spawn()` runs a detached continuation in a context of its own, once, after a delay or repeatedly, in memory. In CAP Java the same is the ChangeSet Context opened around the outermost event, with listeners before and after it closes, cancellation without an exception and Spring's `@Transactional` as an alternative boundary, and the Request Context that carries user, tenant, locale and headers across services and into child threads.","where_it_stops":"At the one database. A root transaction is one connection on one database; nothing spans two services' databases or a remote call, which is what the event queue's dispatch after commit exists for. SQLite allows no parallel transactions and deadlocks two that wait on each other; every asynchronous operation inside a spawned job must be awaited or the handling breaks; in Java a connection is reserved from the pool at the first persistence interaction and a Select starts no transaction unless enforced. Nothing outside the core is mapped here.","sources":[{"url":"https://cap.cloud.sap/docs/node.js/cds-tx","title":"Transaction Management — capire","checked":"2026-09-27","quote":"Whenever an instance of cds.Service processes requests, the core framework automatically cares for starting and committing or rolling back database transactions, connection pooling, principal propagation and tenant isolation."},{"url":"https://cap.cloud.sap/docs/node.js/cds-tx","title":"Transaction Management — capire","checked":"2026-09-27","quote":"Use cds.tx() to start and commit transactions manually, if you need to ensure two or more queries to run in a single transaction."},{"url":"https://cap.cloud.sap/docs/node.js/cds-tx","title":"Transaction Management — capire","checked":"2026-09-27","quote":"In effect, this means the new transaction demarcates a new ACID boundary, while it inherits the event context properties unless overridden in the context argument to cds.tx()."},{"url":"https://cap.cloud.sap/docs/node.js/cds-tx","title":"Transaction Management — capire","checked":"2026-09-27","quote":"Runs the given function as detached continuation in a specified event context (not inheriting from the current one). Options every or after allow to run the function repeatedly or deferred."},{"url":"https://cap.cloud.sap/docs/node.js/cds-tx","title":"Transaction Management — capire","checked":"2026-09-27","quote":"Parallel transactions are not allowed and a new transaction is not started before the previous one is finished."},{"url":"https://cap.cloud.sap/docs/node.js/cds-tx","title":"Transaction Management — capire","checked":"2026-09-27","quote":"Even though the callback function is executed as a background job, all asynchronous operations inside the callback function must be awaited. Otherwise, transaction handling does not work properly."},{"url":"https://cap.cloud.sap/docs/java/event-handlers/changeset-contexts","title":"ChangeSet Contexts — capire","checked":"2026-09-27","quote":"ChangeSet Contexts are used in the CAP Java SDK as a light-weight abstraction around transactions."},{"url":"https://cap.cloud.sap/docs/java/event-handlers/changeset-contexts","title":"ChangeSet Contexts — capire","checked":"2026-09-27","quote":"This has the effect, that by default a ChangeSet Context is opened around the outermost event that was triggered on any service."},{"url":"https://cap.cloud.sap/docs/java/event-handlers/changeset-contexts","title":"ChangeSet Contexts — capire","checked":"2026-09-27","quote":"The ChangeSet Context can be used to cancel a ChangeSet without throwing an exception. All events in the changeset are processed in that case, but the transaction is rolled back at the end."},{"url":"https://cap.cloud.sap/docs/java/event-handlers/changeset-contexts","title":"ChangeSet Contexts — capire","checked":"2026-09-27","quote":"Database transactions in CAP are always started and initialized lazily during the first interaction with the Persistence Service."},{"url":"https://cap.cloud.sap/docs/java/event-handlers/request-contexts","title":"Request Contexts — capire","checked":"2026-09-27","quote":"Request Contexts span the execution of multiple events on (different) services. They provide a common context to these events, by providing user or tenant information or access to headers or query parameters."},{"url":"https://cap.cloud.sap/docs/java/event-handlers/request-contexts","title":"Request Contexts — capire","checked":"2026-09-27","quote":"CAP service calls can be executed in different threads. In most cases the Request Context from the parent thread - typically the worker thread executing the request - needs to be propagated to one or more child threads."},{"url":"https://cap.cloud.sap/docs/node.js/cds-facade#cds-context","title":"The cds Façade Object — capire","checked":"2026-09-27","quote":"Provides access to common event context properties like tenant, user, locale as well as the current root transaction for automatically managed transactions."}]},"changed_in":[{"version":"@sap/cds 5.0.4","date":"2021-04-07","applies_to":{"ecosystems":["cap"],"flavors":["node"]},"what_changed":"An event handler no longer wraps its calls in cds.tx(req) to get context propagation and a managed transaction; the service runtime creates the transaction and propagates the context on its own. The old form still works and is deprecated. Dated from the first 5.0 release published on npm.","invalidates":"Handler code, and the samples it was copied from, that call cds.tx(req) before every read or write as if it were required.","source":{"url":"https://cap.cloud.sap/docs/node.js/cds-tx","title":"Transaction Management — capire","checked":"2026-09-27","quote":"Prior to release 5, you always had to write application code like that to ensure context propagation and correctly managed transactions"}}],"history":[{"date":"2026-09-27","field":"id","from":"none","to":"transaction-management","reason":"Proposed by the capire audit of 2026-09-27 with low confidence, as a page that reads like reference but is where cds.spawn and isolation get misused, the fourth admission test. Both runtimes document it, concurrency-control is a different thing, and no capability carried the context that travels with a transaction. Created by the maintainer's decision."},{"date":"2026-09-27","field":"core_coverage.sources","from":"cds.context named without its reference","to":"cites the façade page's cds.context entry","reason":"capire audit 2026-09-27, judgement pages read a third time: the paragraph names cds.context as what carries user, tenant and locale, and the page that defines it was cited nowhere."}],"drafted_with_ai":true},"sap_delivery":{"door":"cap","all":{"built_in":[{"ref":"artifact:sap-cds","name":"@sap/cds","json":"/artifacts/sap-cds.json"},{"ref":"artifact:cap-java-cds-services-bom","name":"com.sap.cds:cds-services-bom","json":"/artifacts/cap-java-cds-services-bom.json"}],"documented_pattern":[],"announced":[],"packages":[]},"by_flavor":{"node":{"built_in":[{"ref":"artifact:sap-cds","name":"@sap/cds","json":"/artifacts/sap-cds.json"}],"documented_pattern":[],"announced":[],"packages":[]},"java":{"built_in":[{"ref":"artifact:cap-java-cds-services-bom","name":"com.sap.cds:cds-services-bom","json":"/artifacts/cap-java-cds-services-bom.json"}],"documented_pattern":[],"announced":[],"packages":[]}}},"edges":{"use_cases":[],"shared_tasks":[],"related_tasks":[],"options":[{"ref":"artifact:sap-cds","name":"@sap/cds","json":"/artifacts/sap-cds.json","ecosystem":"cap","origin_ring":"sap-official"},{"ref":"artifact:cap-java-cds-services-bom","name":"com.sap.cds:cds-services-bom","json":"/artifacts/cap-java-cds-services-bom.json","ecosystem":"cap","origin_ring":"sap-official"}],"samples":[],"explained_by":[{"ref":"content:sap-cloud-application-programming-model-cap-part-2","name":"SAP Cloud Application Programming Model（CAP）：カスタムロジックの実装 – Part 2","json":"/content/sap-cloud-application-programming-model-cap-part-2.json"}],"normative_context":[]}}