> For the complete documentation index, see [llms.txt](https://docs.rumi.systems/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rumi.systems/rumi-core/guides/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/controlling-transactions.md).

# Controlling Transactions

While Rumi handles transactions automatically for most use cases, it also provides programmatic controls that allow you to fine-tune transaction behavior from within your message handlers. These capabilities are useful for advanced scenarios where you need more control over transaction boundaries and commit behavior.

## Overview

By default, each message handler executes within an implicit transaction that commits automatically when the handler returns. The AEP Engine ensures that:

* Store changes are persisted or replicated
* Outbound messages are queued for sending
* The inbound message is acknowledged
* Consensus is established with cluster members (for Event Sourcing)

For most applications, this automatic transaction management is sufficient. However, Rumi provides transaction control APIs for specialized scenarios.

## Transaction Control Capabilities

### [Using Savepoints](/rumi-core/guides/developing-applications/authoring-user-code/message-processing/processing-messages/handling-messages/controlling-transactions/using-savepoints.md)

Savepoints allow you to commit work incrementally within a long-running handler. This is useful for:

* Processing large batches where you want to commit progress periodically
* Handlers that may fail partway through and need to avoid reprocessing already-completed work
* Reducing transaction replay time during recovery

When you set a savepoint, Rumi commits all work up to that point, including store changes and outbound messages. If the handler subsequently fails, it will resume from the last savepoint rather than replaying from the beginning.

## When to Use Transaction Controls

Consider using transaction controls when:

* **Long-running handlers**: Your handler processes large batches or performs extensive computation
* **Partial failure recovery**: You want to commit intermediate results to avoid reprocessing on failure
* **Memory constraints**: Committing incrementally reduces the amount of buffered state

{% hint style="warning" %}
**Use with Caution**: Transaction controls are advanced features. Most applications should rely on Rumi's automatic transaction management. Only use these controls when you have specific requirements that cannot be met by the default behavior.
{% endhint %}

## See Also

* [Transactions](/rumi-core/concepts/transactions.md) - Conceptual overview of how Rumi transactions work
* [Cluster Consensus](/rumi-core/concepts/microservice-operation/cluster-consensus.md) - How consensus is established
* [Configuring Adaptive Batching](/rumi-core/guides/developing-applications/configuring-the-runtime/transactions/adaptive-batching.md) - Runtime configuration for transaction batching
