10.2 Platform Events Publish & Subscribe
Key Takeaways
- Platform Events are event messages defined like custom objects (API name ending in __e) for near-real-time, loosely coupled communication
- Publish from Apex with EventBus.publish; publish can be partial-success aware via Database.SaveResult-style results
- Subscribe with Apex triggers on the event, Flow, Process-era tools where still relevant, or external CometD/Bayeurx streaming clients
- Standard platform events exist for some platform signals; custom platform events model your domain messages
- High-volume platform events and replay IDs support scalable delivery and subscriber recovery after disconnect
10.2 Platform Events Publish & Subscribe
Quick Answer: Platform Events are durable event messages (
My_Event__e) you publish with EventBus.publish and subscribe via Apex triggers, Flow, or external CometD clients. They enable near-real-time, loosely coupled integration inside and beyond Salesforce without tight synchronous call stacks.
Platform Developer I expects you to place Platform Events among integration and async tools: when to publish an event instead of a direct DML callback, how publish/subscribe work, and what replay means for consumers.
What Is a Platform Event?
A Platform Event is a special Salesforce schema type for messages—not ordinary persistent business records like Account. You define:
- Event name and API name ending in
__e(custom events) - Custom fields for the payload (primitives appropriate to event definitions)
- Publish behavior characteristics (including high-volume options where configured)
Events are publish/subscribe: publishers do not call a specific Apex class; any authorized subscriber can react. That decoupling is the product value.
[Publisher: Trigger / Apex / Flow / API]
| EventBus.publish / UI publish
v
Order_Confirmed__e (message bus)
|
+--------+--------+--------+
v v v v
Apex Flow External Another
trigger CometD org/process
Defining Events (Conceptual Model for the Exam)
In Setup, admins/developers create a Platform Event and fields much like a custom object, but usage patterns differ:
| Aspect | Typical sObject | Platform Event |
|---|---|---|
| API suffix | __c | __e |
| Purpose | Durable business data | Notification / integration message |
| Query habit | SOQL as system of record | Not your long-term CRM datastore |
| Automation | Triggers, Flow on record | Triggers/Flow on event message |
| Coupling | Direct DML to related records | Fire-and-forget message to subscribers |
Standard platform events are provided by Salesforce for certain platform notifications. Custom platform events are what you design for app-specific messages (order submitted, shipment delayed, enrichment completed).
You do not need to memorize every standard event name; you need to know that both standard and custom events exist and that custom ones use the __e suffix and your field set.
Publishing with EventBus.publish
public class OrderEventService {
public static void publishConfirmed(Id orderId, String status) {
Order_Confirmed__e evt = new Order_Confirmed__e();
evt.Order_Id__c = orderId;
evt.Status__c = status;
evt.Confirmed_At__c = System.now();
Database.SaveResult sr = EventBus.publish(evt);
if (!sr.isSuccess()) {
for (Database.Error err : sr.getErrors()) {
System.debug('Publish failed: ' + err.getMessage());
}
}
}
public static void publishBulk(List<Order_Confirmed__e> events) {
List<Database.SaveResult> results = EventBus.publish(events);
// Inspect each SaveResult in bulk-safe fashion
}
}
Exam points:
- Construct the event sObject, set fields, call
EventBus.publish - Publish returns
Database.SaveResult(or a list for bulk) so you can detect failures - Publish is designed for async fan-out—subscribers run in their own contexts; do not treat publish like a synchronous method call that returns subscriber output
- Bulkify: publish a list of events when many records change, not one publish per record in a tight anti-pattern that ignores bulk design (still respect event allocation limits)
When to Publish
Common use cases:
- After successful order/case updates — notify fulfillment automation without recursive trigger spaghetti across packages
- Cross-package or cross-app signals — App A publishes; App B subscribes without compile-time dependency on B’s classes
- Bridge to external systems — external CometD clients listen and push to middleware
- Near-real-time UX — Lightning components or services react quickly without polling SOQL every second
Prefer events when multiple unknown consumers may care, or when you want temporal decoupling (publisher finishes even if a subscriber is slow).
Subscribing Inside Salesforce
Apex triggers on platform events
trigger OrderConfirmedTrigger on Order_Confirmed__e (after insert) {
List<Task> tasks = new List<Task>();
for (Order_Confirmed__e evt : Trigger.new) {
tasks.add(new Task(
Subject = 'Fulfill order ' + evt.Order_Id__c,
Status = 'Not Started',
Priority = 'Normal'
// WhatId/WhoId as appropriate for your model
));
}
if (!tasks.isEmpty()) {
insert tasks;
}
}
Notes:
- Event triggers are typically after insert style for the event message
Trigger.newholds the event messages for the batch- Subscriber Apex is still subject to governor limits for that execution
- Design idempotent subscribers when possible—delivery semantics and retries can surprise brittle code
Flow
Record-triggered-style Platform Event–triggered Flows subscribe declaratively: when Order_Confirmed__e is published, Flow runs actions (create records, send email, call subflows). Exam: both code and declarative subscribers are valid; choose Flow for admin-maintainable reactions, Apex for complex bulk logic.
External subscribers (CometD high-level)
Outside the core app, clients use the Streaming API pattern with CometD (Bayeurx) to subscribe to event channels. High-level exam facts:
- External apps receive near-real-time pushes without polling REST every few seconds
- Authentication and channel selection are required
- This is the bridge from Salesforce publish to middleware, mobile backends, or data lakes
You are not asked to write full CometD JavaScript on the exam; you must know external clients subscribe via CometD/Streaming, while Apex/Flow subscribe natively.
High-Volume Platform Events (Awareness)
Salesforce distinguishes event capacities. High-volume platform events are optimized for greater throughput and scale compared with standard-volume custom events. For Platform Developer I:
- Know that high-volume exists for large-scale eventing
- Publishing and subscribing patterns (
EventBus.publish, triggers, Flow, Streaming) remain the conceptual model - Exact org allocations and delivery guarantees can be release-specific—exam items stress scale choice and architecture, not memorizing every limit table cell
If a scenario says “millions of telemetry notices per day,” high-volume event design is more appropriate than abusing ordinary custom objects as a queue.
Replay IDs Overview
Each event message is associated with a replay id (position in the event stream). Subscribers—especially external Streaming clients—can:
- Connect and receive new events from now on
- Request replay from a stored replay id after disconnect to catch missed events within the retention window
- Use special replay values (for example, replay from earliest retained or tip-only) depending on API options
Why it matters: Near-real-time systems fail when a client restarts and silently skips messages. Replay ids provide a cursor for recovery. Apex high-level triggers process events as published into the platform’s subscriber execution; external clients lean more explicitly on replay for catch-up.
Retention is finite—replay is not infinite archive storage. For permanent audit history, write durable records (custom objects, big objects, external store) from a subscriber if business requires a permanent log.
Platform Events vs Other Async Tools
| Need | Prefer |
|---|---|
| Decouple multiple consumers from one producer | Platform Events |
| Process large CRM data volumes in chunks | Batch Apex |
| Single deferred Apex job with rich state | Queueable |
| Point-to-point callout to one HTTP API | HTTP callout (often from Queueable) |
| User-record automation on insert/update | Trigger / Record-Triggered Flow |
| Long-term queryable business data | Custom objects, not events alone |
Events complement—not replace—triggers. A common pattern: trigger or Flow publishes an event after commit-worthy work; multiple subscribers specialize (notifications, integration, analytics).
Testing Publish Paths
@IsTest
static void publishesOrderEvent() {
Test.startTest();
OrderEventService.publishConfirmed(UserInfo.getUserId(), 'Confirmed');
Test.stopTest();
// Assert subscriber side effects if an event trigger exists,
// or assert publish SaveResult in the service under test
}
In tests, deliver event-triggered logic using the same startTest/stopTest discipline used for other async work where applicable, and assert on durable side effects (tasks created, fields updated) rather than on “bus internals.”
Exam Recognition Checklist
- Custom event API names end with
__e - Publish with
EventBus.publish - Subscribe with Apex trigger, Flow, or CometD externally
- Use for near-real-time, loosely coupled integration
- Replay ids help subscribers recover missed events
- High-volume events address scale
- Events are not a substitute for storing core business records
Master publish/subscribe vocabulary and you can separate Platform Events from Queueable, Batch, and ordinary DML on scenario questions.
How does Apex code publish a custom platform event instance?
Which subscription mechanism is valid for reacting to a platform event inside Salesforce without writing an external client?
What is the primary purpose of a platform event replay id for a Streaming/CometD subscriber?