For the complete documentation index, see llms.txt. This page is also available as Markdown.

Backend Calls

Wrap Apex calls in timeBackendCall(...) to capture durations, start/complete events, and exceptions — with four flexible error-handling scenarios.

Most LWC performance problems live in the round trip to the server. timeBackendCall(methodName, apexCall) is the workhorse for measuring that round trip. It logs the start of the call, waits for the promise, logs completion (with duration), and — if something goes wrong — logs the failure with the same duration baseline plus the exception.

Under the hood it returns a PerformanceCallBuilder, which lets you tune how errors are handled before the call is actually executed.

Basic Usage

productSearch.js
import Triton from 'c/triton';
import searchProducts from '@salesforce/apex/ProductController.searchProducts';

export default class ProductSearch extends LightningElement {
    triton;
    products = [];

    connectedCallback() {
        this.triton = new Triton().bindToComponent('ProductSearch');
        this.triton.trackComponentLifecycle('connected');
    }

    async handleSearch() {
        const searchTerm = this.searchInput.value;

        try {
            const results = await this.triton.timeBackendCall(
                'searchProducts',
                () => searchProducts({ searchTerm })
            ).execute();

            this.products = results;
        } catch (error) {
            this.showErrorMessage('Search failed. Please try again.');
        }
    }
}

Three things to notice:

  1. The Apex call is wrapped in an arrow function so Triton controls when it runs.

  2. methodName ("searchProducts") is the label that ends up on the resulting log records. Use the real Apex method name so logs are easy to find.

  3. .execute() is the trigger — until you call it, no logging or Apex invocation happens.

The Four Error-Handling Scenarios

PerformanceCallBuilder exposes two modifiers that combine into four scenarios. The defaults (built-in logging + rethrow) match what 90% of code wants.

Modifiers
Error handler
Rethrow
When to use

.execute()

Built-in (logs failure)

Yes

Default. The standard try/catch pattern.

.withoutRethrow().execute()

Built-in (logs failure)

No

You want failures logged but don't need an exception in the calling code.

.withCustomErrorHandler(fn).execute()

Custom only

Yes

You want full control over the side effects but the calling code still needs to react.

.withCustomErrorHandler(fn).withoutRethrow().execute()

Custom only

No

Fire-and-forget calls with custom telemetry/UX.

1. Default: log + rethrow

The failure is automatically logged with the method name, duration, and exception, then re-thrown so your catch block runs as usual.

2. Built-in logging, no rethrow

Useful when you want the call to fail silently from a control-flow perspective but still capture the failure log. A null return is your signal that something went wrong.

3. Custom handler + rethrow

Custom handlers receive (error, context) where context is { methodName, duration } for backend calls. Use this when you want to enrich the failure with extra side effects (external monitoring, fancy toasts) but still need an exception to bubble.

4. Custom handler, no rethrow

The most "tolerant" mode — perfect for non-critical operations like notifications, where a failure shouldn't poison the rest of the flow.

Parallel Calls

timeBackendCall returns a builder, and .execute() returns a regular Promise, so you can fan out calls and wait on them with Promise.all. Each call gets its own timing, start log, and completion log.

This pattern is especially powerful for record pages — you instantly get a per-call breakdown of which Apex method is the slow one, instead of staring at a single aggregated load time.

What Gets Logged

For a successful backend call, you get two log entries:

Log
Type
Summary
Notable fields

Start

BACKEND_CALL

Backend call started: <methodName>

action = <methodName>

Completion

BACKEND_CALL

Backend call completed: <methodName>

duration, action = <methodName>

A failure produces the start log plus a Backend call failed: <methodName> entry with duration, the exception details, and the stack trace (unless you've supplied a custom handler).

Best Practices

  • Use the real Apex method name as methodName — searching and grouping logs by method is dramatically easier.

  • Keep the arrow function passed to timeBackendCall thin. Anything you do inside it that isn't the Apex call gets folded into the duration measurement.

  • Lean on withoutRethrow() for fire-and-forget side effects (analytics pings, optional enrichment) so a flaky non-critical call can't break your component.

  • Combine with User Interactions when a single user action triggers multiple backend calls — you'll get a parent interaction record plus children for each call.

Last updated