Platform events are part of Salesforce’s enterprise messaging platform, providing an event-driven messaging architecture to enable apps to communicate inside and outside of Salesforce. An event-driven (or message-driven) software architecture consists of event producers, event consumers, and channels. The architecture is suitable for large distributed systems because it decouples event producers from event consumers, thereby simplifying the communication model in connected systems. One or more subscribers can listen to the same event and carry out actions.
Systems in request-response communication models make a request to a web service or database to obtain information about a certain state. The sender of the request establishes a connection to the service and depends on the availability of the service. Also, the external system pushing data into Salesforce is dependent on the completion of the transaction, i.e. if data is being pushed into an sobject and if there are triggers running on the data being pushed, then the external system must wait until all the business logic in the trigger completes its execution.
In comparison, systems in an event-based model obtain information and can react to it in near real-time when the event occurs. Event producers don’t know the consumers that receive the events. Any number of consumers can receive and react to the same events. Both parties are also not dependent on each other.
The only dependency between producers and consumers is the semantic of the message content.
A platform event is a special kind of Salesforce entity, similar in many ways to an
High-volume platform events are published asynchronously. After the publishing call returns with a successful result, the publish request is queued in Salesforce. The event message might not be published immediately.
High-volume platform event messages are stored for 72 hours. You can retrieve past event messages when using CometD clients to subscribe to a channel.
To know about high-volume platform event default allocations, check the documentation.
When publishing an event message, the result that the API returns contains information about whether the operation was successful and the errors encountered. If the
The returned result also contains the
Systems in request-response communication models make a request to a web service or database to obtain information about a certain state. The sender of the request establishes a connection to the service and depends on the availability of the service. Also, the external system pushing data into Salesforce is dependent on the completion of the transaction, i.e. if data is being pushed into an sobject and if there are triggers running on the data being pushed, then the external system must wait until all the business logic in the trigger completes its execution.
In comparison, systems in an event-based model obtain information and can react to it in near real-time when the event occurs. Event producers don’t know the consumers that receive the events. Any number of consumers can receive and react to the same events. Both parties are also not dependent on each other.
The only dependency between producers and consumers is the semantic of the message content.
A platform event is a special kind of Salesforce entity, similar in many ways to an
sObject
. But- Unlike custom or standard objects, you can’t update or delete event records. All platform event fields are read-only by default.
- You can set read and create permissions for platform events. Grant permissions to users in profiles or in permission sets.
- You can’t restrict access to a particular field. Field-level security permissions don’t apply and the event message contains all fields.
- Because event publishing is equivalent to a DML insert operation, DML limits and other Apex governor limits apply.
Publish Immediately vs Publish After Commit
Platform event messages are published either immediately or after a transaction is committed, depending on the publish behavior you set in the platform event definition.- Publish Immediately: The event message is published when the publish call executes. Select this option if you want the event message to be published regardless of whether the transaction succeeds. Also choose this option if the publisher and subscribers are independent, and subscribers don't rely on data committed by the publisher. For example, the immediate publishing behavior is suitable for an event used for logging purposes. With this option, a subscriber might receive the event message before data is committed by the publisher transaction. The
allOrNone
header is ignored when publishing through the APIs. Some events can be published even when others fail in the same call. - Publish After Commit: The event message is published only after a transaction commits successfully. Select this option if subscribers rely on data that the publishing transaction commits. For example, a process publishes an event message and creates a task record. A second process that is subscribed to the event is fired and expects to find the task record. Another reason for choosing this behavior is when you don't want the event message to be published if the transaction fails. The
allOrNone
header value takes effect. IfallOrNone
is set to true, no events are published if at least one event fails in the same call.
High-Volume Platform Events
In API version 45.0 and later, your new custom event definitions are high volume by default. High-volume platform events offer better scalability than standard-volume platform events.High-volume platform events are published asynchronously. After the publishing call returns with a successful result, the publish request is queued in Salesforce. The event message might not be published immediately.
High-volume platform event messages are stored for 72 hours. You can retrieve past event messages when using CometD clients to subscribe to a channel.
To know about high-volume platform event default allocations, check the documentation.
Publishing Platform Events
- To publish event messages with Process Builder, add a Create a Record action to the appropriate process. Where you'd usually pick an object to create, select the custom platform event.
- To publish event messages with flows, add a Create Records element to the appropriate flow. Where you'd usually pick an object to create, select the custom platform event.
- To publish event messages with Apex, call the
EventBus.publish
method. EachEventBus.publish
method call is considered a DML statement, and DML limits apply. The below code is taken from the documentation to show how to publish platform events with Apex.
List<Low_Ink__e> inkEvents = new List<Low_Ink__e>(); inkEvents.add(new Low_Ink__e(Printer_Model__c='XZO-5', Serial_Number__c='12345', Ink_Percentage__c=0.2)); List<Database.SaveResult> results = EventBus.publish(inkEvents); for (Database.SaveResult sr : results) { if (sr.isSuccess()) { System.debug('Successfully published event.'); } else { for(Database.Error err : sr.getErrors()) { System.debug('Error returned: ' + err.getStatusCode() + ' - ' + err.getMessage()); } } }
- Publish events with Salesforce APIs such as SOAP API, REST API, or Bulk API. To publish a platform event message using REST API, send a POST request to the following endpoint:
/services/data/v48.0/sobjects/Event_Name__e/
When publishing an event message, the result that the API returns contains information about whether the operation was successful and the errors encountered. If the
success
field is true
, the event was published for a standard-volume event. For a high-volume event, the publish request is queued in Salesforce and the event message might not be published immediately. If the success
field is false
, the event publish operation resulted in errors, which are returned in the errors
field.The returned result also contains the
Id
system field. The Id
field value is not included in the event message delivered to subscribers. It is not used to identify an event message, and is not always unique. Subscribers can use the ReplayId
system field, which is included in the delivered message, to identify the position of the event in the stream.Subscribing to Platform Events
- Both processes and flows can subscribe to platform events and receive event messages published through Apex, APIs, flows, or other processes. Both of them provide an auto subscription mechanism.
- To subscribe to event notifications with Apex Triggers, write an
after insert
trigger on the event object type. Onlyafter insert
triggers are supported for platform events because event notifications can’t be updated. They’re only inserted (published).
trigger LowInkTrigger on Low_Ink__e (after insert) { for (Low_Ink__e event : Trigger.New) { ... ... } }
NOTE: In platform event triggers, if you create a Salesforce record that contains anownerId
field, set theownerId
field explicitly to the appropriate user. Platform event triggers run under the Automated Process entity. If you don’t set theownerId
field on records that contain this field, the system sets the default value ofAutomated Process
. - Subscribe to platform events with the empApi component in your Lightning web component or Aura component.
- Use CometD to subscribe to platform events in an external client. The process of subscribing to platform event notifications through CometD is similar to subscribing to PushTopics or generic events. The only difference is the channel name. The platform event channel name is case-sensitive and is in the following format:
/event/Event_Name__e
. Use this CometD endpoint with the API version appended to it:/cometd/48.0
. You can refer the below code to subscribe to a platform event in a Node application.
const jsforce = require("jsforce");
const dotenv = require("dotenv");
const express = require("express");
const session = require("express-session");
dotenv.config({
path: "./config/config.env"
});
const app = express();
// Configure express-session to store Session Id and Instance URL
app.use(
session({ secret: "keyboard cat", resave: true, saveUninitialized: true })
);
const oauth2 = new jsforce.OAuth2({
loginUrl: process.env.SF_LOGIN_URL,
clientId: process.env.SF_CLIENT_ID,
clientSecret: process.env.SF_CLIENT_SECRET,
redirectUri: process.env.SF_REDIRECT_URI
});
app.get("/oauth2/auth", function(req, res) {
res.redirect(
oauth2.getAuthorizationUrl({ scope: "api id web refresh_token" })
);
});
app.get("/oauth2/callback", function(req, res) {
var conn = new jsforce.Connection({ oauth2: oauth2 });
conn.authorize(req.query.code, function(err, userInfo) {
if (err) {
return console.error(err);
}
console.log(userInfo);
console.log(conn.accessToken, conn.refreshToken, conn.instanceUrl);
req.session.accessToken = conn.accessToken;
req.session.instanceUrl = conn.instanceUrl;
res.redirect("/");
});
});
app.get("/", function(req, res) {
if (!req.session.accessToken || !req.session.instanceUrl) {
res.redirect("/oauth2/auth");
return;
}
// Connect and output query results
const conn = new jsforce.Connection({
accessToken: req.session.accessToken,
instanceUrl: req.session.instanceUrl
});
res.send(req.session.instanceUrl);
subscribeToEvents(conn, res);
});
function subscribeToEvents(conn, res) {
conn.streaming.topic("/event/DemoEvent__e").subscribe(function(message) {
console.log(message);
});
}
const PORT = process.env.PORT || 3000;
app.listen(PORT, console.log(`Server running on ${PORT}`));
ReplayId
System Field
Each event message is assigned an opaque ID contained in the ReplayId
field. The ReplayId
field value, which is populated by the system when the event is delivered to subscribers, refers to the position of the event in the event stream. Replay ID values are not guaranteed to be contiguous for consecutive events. A subscriber can store a replay ID value and use it on resubscription to retrieve events that are within the retention window.You can replay platform events that were sent in the past 24 hours. You can replay platform events through the API (CometD) but not Apex. The process of replaying platform events is the same as for other Streaming API events. You can use workbench to replay the platform events.
Standard Platform Events
Salesforce provides events with predefined fields, called standard platform events. An example of a standard platform event isAssetTokenEvent
, which monitors OAuth 2.0 authentication activity. Another example is BatchApexErrorEvent
, which reports errors encountered in batch Apex jobs (check the code for force-brf - a batch retry framework, to understand how to handle such event). You can subscribe to a standard platform event stream using the subscription mechanism that the event supports. Check the documentation to go through all the standard platform events.Limits
Check the documentation to learn about the allocations available for platform event definitions, publishing and subscribing to platform events, and event delivery in CometD clients. The below table provides information about the default allocation for the high-volume events.Please note the following points:
- The maximum event message size that you can publish is 1 MB. If your event object has hundreds of custom fields or many long text area fields, you could hit this limit. In this case, the publishing call gets an error.
- Non-CometD clients, including Apex triggers, processes, and flows, don’t count against the event delivery limit.
- The empApi Lightning component is a CometD client. As a result, the event delivery allocation applies to the component and it is per channel per unique browser session.
- Platform events ARE quite capable when only used “on-platform”. Read this blog to understand in detail.
Some important StackExchange links
- How do I see debug logs for Platform Event triggers in Salesforce?
- Apex Rest Vs Platform Events for Inbound SF integration which one to choose?
Other important links
- Platform Events Record Locking Issue
- Using Salesforce Platform Events to Build a Presence Lightning Component
- Salesforce Platform Events, a quick dive into EventBus.RetryableException