> For the complete documentation index, see [llms.txt](https://triton.pharos.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://triton.pharos.ai/beyond-apex/lwctransaction.md).

# LWC Transaction Management

How Triton manages transactions in LWC — automatic ids, session-storage continuity across components, the auto-flush monitor, and when to take manual control.

A transaction id is what ties a scatter of log records into one story. In LWC, Triton manages that id for you automatically — creating it, persisting it across component lifecycles, and flushing logs on a timer so nothing gets stranded. Most of the time you never think about it. This page is for the times you do.

## It's automatic by default

The moment you create a logger, transaction handling kicks in. Behind the scenes Triton:

1. Looks for an existing transaction id in session storage.
2. Reuses it if found; generates a fresh UUID v4 if not.
3. Starts an auto-flush monitor that watches the buffer.

{% code lineNumbers="true" %}

```javascript
connectedCallback() {
    this.triton = new Triton().bindToComponent('LogDemo');
    // transaction id is already set and shared
}
```

{% endcode %}

Because the id lives in **session storage**, it survives component teardown and is shared across every Triton logger on the page. Two sibling components logging in the same session automatically land under the same transaction — no wiring required.

{% code lineNumbers="true" %}

```javascript
async handleOperation() {
    try {
        this.triton.log(
            this.triton.info(TYPE.FRONTEND, AREA.ACCOUNTS).summary('Operation started')
        );
        await this.performOperation();
        this.triton.log(
            this.triton.info(TYPE.FRONTEND, AREA.ACCOUNTS).summary('Operation completed')
        );
    } catch (error) {
        this.triton.log(
            this.triton.exception(error).summary('Operation failed')
        );
    }
}
```

{% endcode %}

Every `log()` above gets the current transaction id stamped on it, so all three correlate in the database — ready to view as one grouped trace.

## The auto-flush monitor

Buffered logs don't wait forever. Triton runs a background monitor that:

* **checks the buffer every 5 seconds**, and
* **flushes any log that's been sitting for more than 10 seconds.**

This is what keeps logs from being lost when a user wanders off mid-session or a component is destroyed before you flush by hand. You still get the batching benefit — logs published together — without the risk of a buffer that never drains.

It's a safety net, not a substitute for flushing at real boundaries. For anything critical, still use `logNow()` (see [LWC](/beyond-apex/lwc.md#buffered-vs-immediate)), and flush explicitly when a component tears down:

{% code lineNumbers="true" %}

```javascript
disconnectedCallback() {
    if (this.triton) {
        this.triton.flush();
    }
}
```

{% endcode %}

## Manual transaction control

When you want explicit boundaries, three methods give it to you:

{% code lineNumbers="true" %}

```javascript
this.triton.startTransaction();               // new id, fresh span context, cleared marks
this.triton.resumeTransaction(existingId);    // adopt an existing id
this.triton.stopTransaction();                // flush pending logs, then clear the id
```

{% endcode %}

* **`startTransaction()`** generates a new UUID v4, stores it in session storage, resets the span context, clears any active performance marks, and (re)starts the auto-flush monitor. Everything logged afterward uses the new id.
* **`resumeTransaction(id)`** adopts an id you already have — the key to correlating with an existing transaction (e.g. one that started in Apex). See [LWC and Apex](/beyond-apex/lwc-and-apex.md).
* **`stopTransaction()`** flushes anything pending, stops the monitor, and removes the id from session storage — guaranteeing your logs are saved before the transaction ends.

### When manual control pays off

The classic case is a **multi-step flow** you want captured as one unit:

{% code lineNumbers="true" %}

```javascript
// A wizard: one transaction across all steps
async handleWizardNavigation() {
    if (this.isFirstStep) {
        this.triton.startTransaction();
    }
    try {
        this.triton.log(
            this.triton.info(TYPE.FRONTEND, AREA.ACCOUNTS)
                .summary(`Wizard step ${this.currentStep} completed`)
        );
        await this.processCurrentStep();
        if (this.isLastStep) {
            this.triton.stopTransaction();   // close it out, flush everything
        }
    } catch (error) {
        this.triton.stopTransaction();
        throw error;
    }
}
```

{% endcode %}

The same shape works for a batch-processing UI where you want every record's logs grouped under one parent — `startTransaction()` at the top, `stopTransaction()` in a `finally`.

## Do / Don't

* **Do** let Triton manage transactions automatically for ordinary work — single API calls, form submits, standard CRUD. The defaults are right for the common case.
* **Do** reach for manual control when you have a genuine multi-step boundary, and always pair `startTransaction()` with a `stopTransaction()` (a `finally` is your friend).
* **Do** flush in `disconnectedCallback` so a teardown never strands buffered logs.
* **Don't** call `startTransaction()` on every interaction — you'll fragment what should be one grouped trace into many.

{% hint style="info" %}
Manual transactions are also how you hand off a trace to another layer. Grab the current id from `this.triton.transactionId`, pass it to Apex, and `resumeTransaction(id)` there. That's the foundation of [End-to-End Logging](/end-to-end.md).
{% endhint %}
