Skip to main content
New tool CRON Expression Builder — preview next run times before you schedule Apex. Open the builder →
Diagram showing Platform Events triggering a refreshApex call to update LWC data in Salesforce.
LWC

Refresh LWC data with Platform Events and refreshApex

Ever update a record in Salesforce only to see your custom LWC still showing old data? This guide shows you how to use Platform Events as a notification bell to trigger a refresh. It is a much cleaner way to keep your UI in sync without using messy timers.

The short answer

This article explains how to automatically refresh Lightning Web Component data after backend updates by combining Platform Events with refreshApex. It demonstrates how to publish an event from an Apex trigger and subscribe via lightning/empApi to refresh wired data instantly without page reloads.

Key takeaways Publish Platform Events from backend triggers or Flows as notification signals instead of using timers or polling to refresh LWC data. Store the complete object provisioned by the @wire adapter so it can be passed directly to refreshApex(). Filter Apex triggers to fire Platform Events only when specific displayed fields change to avoid event storms and conserve daily limits. Unsubscribe from the Platform Event channel in disconnectedCallback to avoid memory leaks in production components.

Why it's hard to refresh LWC data automatically

Ever had that moment where you update a field on a standard Salesforce page, but your custom LWC just sits there showing old data? It's a classic headache. To refresh LWC data effectively in these scenarios, we need a way to tell the component that something happened on the server.

Standard components and custom LWCs live in their own little worlds. If a Flow or a Trigger updates a record in the background, your @wire method doesn't always know it needs to run again. This is especially true if the update happened via an automated process or a different user. So, how do we bridge that gap?

A technical diagram illustrating the synchronization gap between a Salesforce background Flow update and a front-end Lightning Web Component UI.

A technical diagram illustrating the synchronization gap between a Salesforce background Flow update and a front-end Lightning Web Component UI.

A better way to refresh LWC data using Platform Events

I've seen teams try to use timers or constant polling to keep data fresh. But honestly, that's a waste of resources and usually leads to performance lag. A much cleaner approach is to use a Platform Event as a "notification bell."

The logic is simple. When a record changes in the backend, we fire off a Platform Event. Your LWC listens for that specific event and, once it hears it, triggers refreshApex(). It's a lightweight way to refresh LWC data without overcomplicating your architecture.

One thing that trips people up is "event storms." Make sure you only publish your Platform Event when the specific fields you care about actually change. Don't just fire it on every single update or you'll hit your daily limits fast.

Step 1: Create the Platform Event

First, you need to head over to Setup and create a new Platform Event. Let's call it Refresh_Custom_Components__e. You don't even need custom fields for this specific pattern. The event itself acts as the signal. If you're deciding between different messaging tools, this guide on Platform Events can help you understand why they're perfect for this.

Step 2: Fire the event from your Trigger

Now, we need to publish that event. You can do this from a Flow, but if you're already working in Apex, a trigger is usually the way to go. Here is a simple example of how to hook this into an Opportunity trigger.

trigger OpportunityTrigger on Opportunity (after update) {
    if (Trigger.isAfter && Trigger.isUpdate) {
        List<Refresh_Custom_Components__e> events = new List<Refresh_Custom_Components__e>();
        events.add(new Refresh_Custom_Components__e());
        EventBus.publish(events);
    }
}

In a real project, I'd suggest moving this logic into a helper class. You want to keep your triggers thin. But for this example, the main point is just getting that EventBus.publish() call to run when the data changes.

Step 3: Wiring the LWC to listen and refresh

This is where the magic happens. We'll use lightning/empApi to subscribe to our event channel. Usually, communication between components happens via standard events, but since this is coming from the backend, empApi is our best friend.

import { LightningElement, api, wire } from "lwc";
import { refreshApex } from "@salesforce/apex";
import getOppty from "@salesforce/apex/OpptiesOverAmountApex.getOpptyOverAmount";
import { subscribe, onError } from 'lightning/empApi';

export default class OpportunitiesOverAmount extends LightningElement {
    @api recordId;
    wiredOpptyResult;

    @wire(getOppty, { recordId: "$recordId" })
    wiredOppty(result) {
        this.wiredOpptyResult = result;
    }

    connectedCallback() {  
        const self = this;
        const messageCallback = function (response) {
            console.log('Event received: ', response);
            // This is the call that actually updates the UI
            refreshApex(self.wiredOpptyResult);
        };

        subscribe('/event/Refresh_Custom_Components__e', -1, messageCallback).then(response => {
            console.log('Successfully subscribed to channel');
        });
    }
}

And that's it. When the trigger fires the event, the LWC catches it and tells refreshApex to go grab the latest data. It feels much more responsive to the end user because the UI updates almost instantly after the record is saved.

Key Takeaways to refresh LWC data

  • Use Platform Events as signals: You don't always need to pass data in the event; sometimes just knowing "something changed" is enough.
  • Remember the wired property: To use refreshApex, you must capture the entire object returned by the wire, not just the data property.
  • Filter your triggers: Only publish the event if the specific fields displayed in your LWC have changed.
  • Handle unsubscriptions: In a production component, make sure to unsubscribe in the disconnectedCallback to prevent memory leaks.

Look, there are other ways to do this, like using the new RefreshView API, but that doesn't always work if the change happens entirely in the backend. This Platform Event pattern is a reliable fallback I've used on dozens of projects. It's simple, it's fast, and it just works.

Give this a try the next time your users complain about having to hit the browser refresh button to see their updates. It makes the whole experience feel a lot more modern.

Frequently asked questions

How do you refresh LWC data when a record updates in the backend?

Publish a custom Platform Event from an Apex trigger or Flow when record data changes. In your LWC, subscribe to that event channel using lightning/empApi and invoke refreshApex() inside the message callback to fetch the latest data.

Why is refreshApex not working with wired data in LWC?

The refreshApex() function requires the entire response object provisioned by the @wire service, not just the unwrapped data property. Assign the full wire result to a component property and pass that variable into refreshApex().

How do you avoid Platform Event limits when refreshing LWC components?

Filter your trigger logic so that EventBus.publish() executes only when specific fields tracked by your component are modified. This prevents event storms and ensures you do not exhaust daily publication limits.

Newsletter

One email every Tuesday

New guides, tool updates, and the release-note changes that break things.

No spam. Unsubscribe in one click.

Comments

Loading comments...

Leave a Comment