Event-driven architectures are great for decoupling and scalability. In this post, we’ll look at a couple of Salesforce Platform features that help developers use platform events and Change Data Capture events at scale. We’ll start with a refresher on streaming events and we’ll explore the concept of custom channels. We’ll then dive into event filtering and change event field enrichment.

A refresher on streaming events

There are a number of different types of streaming events that are available on the Salesforce Platform. In the context of this post, we’ll only focus on modern event types: platform events and change events.

Platform events are events that are triggered from code, automation tools like Flow, or API calls from outside of the Salesforce Platform. These events are used to broadcast custom messages in the context of integrations. You control the shape and content of platform events by creating custom fields like you would when creating custom objects (although field types are limited).

Change Data Capture events (or change events in short) are events that are automatically sent in near real-time by the Salesforce Platform when a record is created, modified, deleted, or undeleted. The shape of change events closely mirrors the shape of their related object: an account change event contains a few change event base fields plus the fields of the account object. You can’t manually fire change events or define custom change events fields.

Platform and change events are powerful tools for building event-driven integrations. They become even more powerful when used at scale in conjunction with custom channels.

Work with custom channels

For starters, you can work with individual standard and custom events but at some point, you can go further and create custom channels to unlock additional features. Custom channels allow you to group multiple events together, as well as work with filters and enrichment (we’ll cover those in the next sections).

Custom channels (PlatformEventChannel metadata object, see docs) are composed of one or more channel members (PlatformEventChannelMember metadata object, see docs). A member is tied to a standard or custom platform event or change event. A given channel cannot mix event types: it’s either composed of platform events or change events.

Entity relationship diagram for channel and channel member
As of Spring ’23, custom channels and members must be declared and edited via the Tooling or the Metadata API. For example, to create a custom channel that contains change events with the Tooling API, run a POST request on the endpoint shared below (replace INSTANCE_URL with your org’s instance URL).

Use the following JSON for the request body.

Request highlights:

  • FullName is the API name of the custom channel. It must end with __chn.
  • channeType sets the type of members that the channel supports. Its value is either data for Change Data Capture events or event for platform events.

Once you’ve declared a custom channel, you can add members to it by calling this endpoint:

Use the following JSON for the request body.

Request highlights:

  • FullName is the API name of the custom channel member. You are free to name it the way you want, but a convention is to concatenate the channel API name with the selected entity name. Note that this field does not allow double underscores, so you must modify the channel API name suffix to simply _chn instead of __chn.
  • eventChannel maps to the channel API name (the value of the FullName attribute of the previous request).
  • selectedEntity maps to a platform event or change event API name. In this example, AccountChangeEvent is the standard change event for the Account object.

After adding a channel member, you can repeat the operation and add other members. In the previous example, you’d want to add another member that tracks standard Contact change events.

Custom channels become even more powerful when you add the ability to specify event filters and enrich change events data.

Filter events

Complex orgs generate large amounts of events. This can be problematic for your integrations when you need to discriminate relevant events from “noise.” Not only do you need to handle filtering logic on the client side, but you also consume more events and this impacts your org’s limits.

Diagram presenting large volumes of events being sent to a client and the need to filter them before processing
Thankfully, you no longer need to subscribe to all events and do the filtering with some pre-processing logic on the client side, you have the ability to specify platform event filters and change event filters on the platform side.

Diagram presenting relevant events being sent to a client thanks to event filtering

When registering custom channel members, you have access to a filterExpression field that lets you specify some logic to filter events based on operation types and field values. Filter expressions are based on SOQL and support a subset of SOQL operators and field types with a few limitations.

For example, you can apply a filter on account change events to only receive update operations for records in the agriculture or banking industry with this channel member definition:

In addition to event filters, you can also use custom channels to enrich change events with extra fields.

Enrich change events

When integrating with a third-party system, you generally want to use an external ID to link a Salesforce Platform record with their representation in the other system. This external ID is likely immutable, so this creates a challenge when working with Change Data Capture since only changed fields are sent as part of the events. Thanks to field enrichment, you can now specify up to ten fields that will always be sent in change events.

Diagram presenting change event field enrichment

To benefit from enriched fields, simply specify the enrichedFields attribute on channel members and declare a list of enriched fields. For example, this definition adds the custom External_Id__c field to account change events:

Note: Fields that are part of filter expressions are automatically added to change events, so no need to declare them as enriched fields.


Whether you use the Streaming API to integrate with CometD or the new Pub Sub API, be sure to take advantage of custom channels. Custom channels help you scale operations with event filtering and change event field enrichment. These features allow you to remove event filtering logic from clients, decrease the number of events being sent (reduces org’s limit consumption), and facilitate record reconciliation in clients.

We’ll leave with two helpful tools: the Salesforce Platform APIs Postman collection helps you manage custom channels with some Tooling API request templates, and the Streaming Monitor allows you to subscribe to your custom channels.


About the author

Philippe Ozil is a Principal Developer Advocate at Salesforce where he focuses on the Salesforce Platform. He writes technical content and speaks frequently at conferences. He is a full-stack developer and enjoys working on DevOps, robotics, and VR projects. Follow him on Twitter @PhilippeOzil or check his GitHub projects @pozil.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS