Platform Events in Salesforce — A Complete Guide for Beginners
Real-time messaging, event-driven architecture, Apex + LWC, ReplayId, and 10 interview practice questions — beginner friendly.
Platform Events in Salesforce — A Complete Guide for Beginners
Real-time messaging, event-driven architecture, and everything you need to know before your next Salesforce interview — explained simply with actual code.
Before we start — why should you care about Platform Events?
If you're preparing for a Salesforce Developer interview, Platform Events is one of those topics that separates candidates who just know the basics from those who actually understand how modern Salesforce architecture works.
It shows up in job descriptions, interview rounds, and real projects — especially anything involving integrations, real-time updates, or connecting Salesforce with external systems. By the end of this guide, you'll be able to explain it clearly, write working code, and answer the tricky follow-up questions interviewers love to throw at you.
What problem does Platform Events actually solve?
To understand Platform Events, you first need to understand the problem with traditional integrations.
In a typical REST or SOAP integration, System A calls System B directly and waits for a response. This is called a tightly coupled architecture. It works — until it doesn't. If System B is slow, System A is slow. If System B is down, System A fails. One broken link breaks the entire chain.
Now imagine you're building an order management system where Salesforce needs to notify a warehouse system, a shipping partner, and an internal dashboard — all at the same time. With tight coupling, you'd have to call all three sequentially, handle each failure separately, and hope nothing goes wrong mid-transaction.
Platform Events solves all of this elegantly.
When you order food on Swiggy, you place the order and move on with your evening. You don't stand at the door waiting. Swiggy (the Event Bus) holds the order. The restaurant gets notified independently. The delivery person gets notified independently. Three things happen — none of them blocked by the others. That's exactly the publish-subscribe model Platform Events uses.
So what exactly are Platform Events?
Platform Events are Salesforce's enterprise messaging framework built on Event-Driven Architecture (EDA). They allow systems — inside and outside Salesforce — to communicate asynchronously in real-time through a publish-subscribe model.
There are three players in every Platform Event flow:
Apex / Flow / External App
Holds events for 72 hours
Apex Trigger / LWC / Flow / External
The publisher fires the event and immediately moves on — this is the "fire and forget" model. The Event Bus holds the message. One or many subscribers can react to it independently, at their own pace. None of them are directly connected to each other.
In Salesforce, Platform Event objects are defined just like custom objects — except they use the __e suffix instead of __c. For example: Order_Notification__e.
Publish Behavior — the concept most beginners miss
When you create a Platform Event in Salesforce Setup, you have to choose its Publish Behavior. This single setting has a huge impact on how your event interacts with database transactions — and it's one of the first things a senior interviewer will ask about.
"Choosing the wrong Publish Behavior is the difference between data integrity and data corruption. I always match the behavior to the business context — Publish After Commit for processes, Publish Immediately for logging."
How to publish a Platform Event in Apex
Publishing a Platform Event in Apex is straightforward. The key rule: always use EventBus.publish() — never use insert directly. Using EventBus.publish() gives you proper error handling and respects the Publish Behavior setting you configured in Setup.
// Step 1: Create the event instance with your data
Order_Notification__e event = new Order_Notification__e(
Order_Id__c = 'ORD-12345',
Status__c = 'Shipped',
Message__c = 'Your order is on the way!'
);
// Step 2: Publish using EventBus — not insert
Database.SaveResult result = EventBus.publish(event);
// Step 3: Always check the result
if (result.isSuccess()) {
System.debug('Event published successfully!');
} else {
for (Database.Error err : result.getErrors()) {
System.debug('Publish failed: ' + err.getMessage());
}
}Never publish events inside a for loop. Always collect events in a List and publish them in bulk using EventBus.publish(eventList) — this keeps you within governor limits.
How to subscribe using an Apex Trigger
Subscribing to a Platform Event via Apex means writing a trigger on the event object. But Platform Event triggers are different from standard object triggers in two important ways.
First — they only support after insert. No before insert, no update, no delete. Second — the trigger runs asynchronously in its own separate transaction. This means it runs completely outside the publisher's transaction context, which has important implications we'll cover in a moment.
trigger OrderNotificationTrigger on Order_Notification__e (after insert) {
for (Order_Notification__e event : Trigger.new) {
System.debug('Order received: ' + event.Order_Id__c);
System.debug('Status: ' + event.Status__c);
System.debug('Message: ' + event.Message__c);
// Add your downstream business logic here
// e.g. create a Task, update a record, call a service
}
}If your trigger processing fails and you want Salesforce to automatically retry, you can throw an EventBus.RetryableException. Salesforce will retry delivery up to 9 times before giving up.
How to subscribe using a Lightning Web Component
This is where Platform Events get really powerful for UI development. Using the lightning/empApi module (Enterprise Messaging Platform API), an LWC can listen for events and update the UI in real-time — without the user ever refreshing the page.
Think of a live order tracking dashboard, a real-time notification bell, or a support queue that updates as new tickets come in. All of this is powered by Platform Events + empApi.
// orderListener.js
import { LightningElement } from 'lwc';
import { subscribe, unsubscribe } from 'lightning/empApi';
export default class OrderListener extends LightningElement {
subscription = {};
channelName = '/event/Order_Notification__e';
connectedCallback() {
subscribe(this.channelName, -1, (event) => {
const payload = event.data.payload;
console.log('Order ID :', payload.Order_Id__c);
console.log('Status :', payload.Status__c);
// Update your component's reactive properties here
}).then(response => {
this.subscription = response; // Save for unsubscribe
});
}
disconnectedCallback() {
unsubscribe(this.subscription, () => {
console.log('Unsubscribed successfully');
});
}
}Always call unsubscribe() in disconnectedCallback(). Forgetting this causes memory leaks and can push your org toward the concurrent CometD subscriber limit — a production issue that's very hard to debug.
ReplayId — what makes Platform Events fault-tolerant
Every event published to the Event Bus gets a unique, sequential number called a ReplayId. Think of it like a ticket number in a queue. Subscribers can use this number to replay events they missed — for example, if a subscriber was offline or experienced an error.
This is what makes Platform Events fault-tolerant. A subscriber doesn't need to be online at the exact moment an event fires. As long as it comes back within 72 hours, it can pick up right where it left off.
| ReplayId value | What the subscriber does | When to use it |
|---|---|---|
-1 | Subscribes to new events only (from now) | Normal real-time subscriptions |
-2 | Replays all events from the last 72 hours | After a system outage or deployment |
| Specific ID | Replays all events after that specific event | Resuming from a known checkpoint |
"ReplayId is what makes Platform Events fault-tolerant — if a subscriber goes offline, it can resume from exactly the right checkpoint rather than missing events or reprocessing everything from scratch."
The Automated Process User — a trap most beginners walk into
This is one of the most important real-world gotchas with Platform Events, and very few beginners know about it. When a Platform Event trigger fires, it doesn't run as the user who published the event. It runs under a special system user called the Automated Process user.
This causes two real problems in production:
Problem 1: If you write UserInfo.getUserId() inside your trigger to capture who triggered the event, you'll get the Automated Process user's ID — not the actual user's ID.
Problem 2: The Automated Process user often doesn't have access to records protected by org-wide defaults or sharing rules. So your SOQL queries inside the trigger might return zero results — even when the records clearly exist — simply because the running user has no visibility to them.
If you need the actual user's identity, publish it as a field on the event itself before sending it. And always test your Platform Event triggers with sharing scenarios — not just in System Administrator context.
When to use Platform Events — and when not to
Platform Events are powerful, but they're not the right tool for every problem. Knowing when to use them — and when a simpler solution works — is itself a sign of senior-level thinking.
- You need real-time notifications across systems
- You want to decouple a publisher from multiple subscribers
- You're integrating Salesforce with external apps asynchronously
- You need live UI updates in LWC without page refresh
- You want fault-tolerant event replay using ReplayId
- You need a synchronous response (e.g. payment verification)
- It's simple single-org automation — use Flow instead
- Your daily event volume exceeds org limits
- You need two-way communication — events are one-directional
- You need permanent storage — 72 hrs and events are gone
"Platform Events transform Salesforce from a monolithic database into a scalable, event-driven integration hub — where every system communicates through events, not direct dependencies."
10 questions to test yourself
You've read the guide — now close it and try to answer these from memory. These are real questions that come up in Salesforce interviews for developers with 0–2 years of experience. No answers provided. That's intentional.
EventBus.publish() instead of insert?