Skip to content

Event-Driven Architecture

Event-driven architecture (EDA) decouples systems by communicating through events rather than direct API calls. Salesforce provides multiple event technologies — choosing the right one is a common CTA differentiator between candidates who pass and those who fail.


Why Event-Driven?

Traditional request-response integration creates tight coupling. When System A calls System B directly, System A must know about System B, handle its failures, and wait for its response. Event-driven architecture breaks this coupling.

AspectRequest-ResponseEvent-Driven
CouplingTight — caller knows calleeLoose — publisher does not know subscribers
AvailabilityCaller blocked if callee is downPublisher unaffected by subscriber failures
ScalabilityLimited by slowest participantSubscribers scale independently
LatencySynchronous waitAsynchronous processing
ComplexitySimple for 1:1Simple for 1:many
Error handlingDirect (caller gets error)Indirect (needs monitoring, DLQ)

Salesforce Event Technologies Comparison

FeaturePlatform EventsChange Data CaptureStreaming API (PushTopic)Pub/Sub API
PurposeCustom business eventsData change notificationsSOQL-based change notificationsHigh-throughput event streaming
Event definitionCustom (you define schema)Automatic (mirrors object fields)SOQL querySubscribes to PE/CDC channels
Publish mechanismApex, Flow, API, Process Builder (deprecated)Automatic on record changeAutomatic on record changegRPC publish
Subscribe mechanismApex Trigger, Flow, API, LWCApex Trigger, Flow, API, LWCCometD clientgRPC subscribe
Retention72 hours (high-volume) / 24 hours (standard)3 daysNo replay storageDepends on event type
ReplayYes (replay ID)Yes (replay ID)LimitedYes (managed subscriptions)
DeliveryAt-least-onceAt-least-onceAt-most-onceAt-least-once
StatusActive, strategicActive, strategicMaintenance modeActive, strategic
CTA relevanceHighHighLow (legacy)High

Platform Events

Custom-defined events that represent business occurrences. You control the schema (fields) and semantics (what the event means).

When to Use

  • Custom business events not tied to a single record change (e.g., OrderSubmitted, PaymentProcessed)
  • Decoupling Salesforce from external systems
  • Broadcasting events to multiple subscribers
  • Triggering flows or processes from external systems

Architecture

flowchart TB
    subgraph Publishers
        APEX[Apex Code]
        FLOW[Flow]
        API[External API Call]
    end

    subgraph "Salesforce Event Bus"
        PE[Platform Event Channel<br/>e.g., Order_Event__e]
    end

    subgraph Subscribers
        TRIGGER[Apex Trigger<br/>after insert]
        FLOW_SUB[Flow<br/>Record-Triggered]
        LWC[Lightning Web Component<br/>Empiri API]
        EXT[External Subscriber<br/>Pub/Sub API / CometD]
    end

    APEX -->|EventBus.publish| PE
    FLOW -->|Create Records| PE
    API -->|POST /sobjects/Order_Event__e| PE

    PE --> TRIGGER
    PE --> FLOW_SUB
    PE --> LWC
    PE --> EXT

Key Characteristics

  • Standard volume: 25 events per Apex transaction, 24-hour retention
  • High volume: Unlimited publish from Apex, 72-hour retention (requires enablement)
  • Publish behavior: EventBus.publish() is independent of DML transaction — events publish even if the transaction rolls back (unless using setSavepoint() with platform events)
  • Subscribe in Apex: Use after insert trigger on the event object

Transaction independence

Platform Events publish independently of the DML transaction by default. If you publish an event and then the transaction rolls back, the event is STILL published. Use the Publish After Commit behavior setting on the event definition to tie publishing to transaction success. This is a critical CTA detail.

Standard vs High-Volume Platform Events

Standard-volume deprecation

Standard-volume platform events can no longer be created as of 2025. Existing standard-volume events continue to function, but full retirement is scheduled for Summer ‘27. All new platform event definitions should use high-volume. Plan migration of existing standard-volume events before the retirement date.

FeatureStandard Volume (deprecated)High Volume
Publish limit per transaction25No Apex limit
Retention24 hours72 hours
AllocationIncluded in orgRequires entitlement
ReplayYesYes
StatusNo new creation; retirement Summer ‘27Active, strategic
Use caseLegacy low-volume business eventsAll new platform event implementations

Change Data Capture (CDC)

Automatically publishes events when records are created, updated, deleted, or undeleted. No custom event definition needed — CDC mirrors the object’s fields.

When to Use

  • Synchronizing Salesforce data changes to external systems
  • Audit trails for data changes
  • Populating data lakes or warehouses in near-real-time
  • When you need to know WHAT changed (field-level change tracking)

Architecture

flowchart LR
    subgraph "Salesforce"
        USER[User/Process] -->|Creates/Updates Record| OBJ[Account, Contact, etc.]
        OBJ -->|Automatic| CDC_ENGINE[CDC Engine]
        CDC_ENGINE -->|Publishes| CDC_EVENT[AccountChangeEvent]
    end

    subgraph "Subscribers"
        CDC_EVENT --> APEX_SUB[Apex Trigger]
        CDC_EVENT --> EXT_SUB[External System<br/>via Pub/Sub API]
        CDC_EVENT --> FLOW_SUB[Flow]
    end

CDC Event Payload

CDC events include rich change information:

FieldDescription
ChangeEventHeaderChange type (CREATE/UPDATE/DELETE/UNDELETE), changed fields, record IDs
changedFieldsList of field API names that changed
Record fieldsCurrent values of changed fields
commitTimestampWhen the change was committed
transactionKeyGroups changes from the same transaction

Key Characteristics

  • Retention: 3 days
  • Objects: Standard and custom objects (select which to enable)
  • Enriched events: Includes which fields changed and their new values
  • Gap events: Published when CDC detects missed events, prompting subscribers to refresh
  • Composite changes: Multiple record changes in one transaction are grouped

CDC vs Platform Events

Decision FactorUse CDCUse Platform Events
Need to track data changesYes — automaticNo — you would have to build it
Custom event semanticsNo — tied to object schemaYes — you define the meaning
Field-level change trackingBuilt-in (changedFields)Must include manually
Multiple objectsEnable per objectOne event definition per use case
External publishingNo (Salesforce only)Yes (API, external systems)

CDC vs Platform Events: Side-by-Side Architecture

The following diagram shows how CDC and Platform Events flow through different paths on the same underlying event bus infrastructure.

flowchart TB
    subgraph Triggers["What Triggers the Event"]
        DML["Record DML<br/>(create/update/delete)"]
        BIZ["Business Logic<br/>(Apex, Flow, API)"]
    end

    subgraph EventBus["Salesforce Event Bus (shared infrastructure)"]
        CDC_CH["CDC Channel<br/>AccountChangeEvent<br/>ContactChangeEvent"]
        PE_CH["Platform Event Channel<br/>Order_Submitted__e<br/>Payment_Processed__e"]
    end

    subgraph Payload["Event Payload"]
        CDC_PAY["CDC Payload<br/>changeType: UPDATE<br/>changedFields: [Phone, Email]<br/>All changed field values<br/>transactionKey, commitTimestamp"]
        PE_PAY["PE Payload<br/>Custom fields you define<br/>e.g., OrderId__c, Amount__c<br/>Status__c, CorrelationId__c"]
    end

    DML -->|"Automatic<br/>(zero code)"| CDC_CH
    BIZ -->|"Explicit publish<br/>(EventBus.publish)"| PE_CH

    CDC_CH --- CDC_PAY
    PE_CH --- PE_PAY

    CDC_CH -->|"3-day retention"| SUB1[Subscribers]
    PE_CH -->|"24h std / 72h HV retention"| SUB1

They share the same daily delivery allocation

Platform Events and CDC share the same delivery allocation (50,000/hour standard, higher with add-ons). In scenarios with high-volume CDC enabled on many objects, ensure you budget the shared allocation carefully. A common CTA trap is enabling CDC on too many objects and starving Platform Event delivery.


Pub/Sub API (gRPC)

The modern event streaming API that replaces CometD-based Streaming API. Uses gRPC for high-performance bidirectional streaming.

When to Use

  • External systems subscribing to high volumes of Platform Events or CDC
  • When you need managed subscriptions (server-side cursor tracking)
  • When CometD performance is insufficient
  • Modern microservices architectures using gRPC

Key Advantages Over Legacy Streaming

FeatureStreaming API (CometD)Pub/Sub API (gRPC)
ProtocolHTTP long-pollinggRPC (HTTP/2)
PerformanceModerateHigh throughput
Subscription managementClient-managedServer-managed (optional)
EncodingJSONAvro (compact binary)
BidirectionalSubscribe onlyPublish and subscribe
FutureMaintenance modeStrategic direction

Managed Subscriptions

Pub/Sub API supports managed subscriptions where the server tracks the subscriber’s position (replay cursor). If the subscriber disconnects and reconnects, it resumes from where it left off — without the client needing to store replay IDs.

sequenceDiagram
    participant External System
    participant Pub/Sub API
    participant Event Bus

    External System->>Pub/Sub API: Subscribe (managed subscription)
    Pub/Sub API->>Event Bus: Register cursor position
    Event Bus-->>External System: Stream events
    Note over External System: External system processes events
    External System->>Pub/Sub API: Acknowledge (commit cursor)
    Note over External System: System disconnects
    External System->>Pub/Sub API: Reconnect
    Pub/Sub API->>Event Bus: Resume from last committed cursor
    Event Bus-->>External System: Continue streaming from checkpoint

Pub/Sub API gRPC Bidirectional Streaming

The gRPC protocol enables full bidirectional streaming over a single HTTP/2 connection. The client and server operate independently — sending and receiving messages simultaneously without blocking. This is fundamentally different from REST polling.

sequenceDiagram
    participant Client as External Client<br/>(gRPC)
    participant PubSub as Pub/Sub API<br/>Endpoint
    participant Bus as Event Bus<br/>(Avro Store)

    Note over Client,PubSub: HTTP/2 connection established (persistent)

    rect rgb(232, 245, 233)
        Note over Client,Bus: Subscribe Flow (pull-based)
        Client->>PubSub: ManagedFetchRequest<br/>(subscription name, batch size)
        PubSub->>Bus: Fetch events from cursor position
        Bus-->>PubSub: Avro-encoded event batch
        PubSub-->>Client: ManagedFetchResponse<br/>(events + replay IDs)
        Client->>Client: Process event batch
        Client->>PubSub: CommitReplayRequest<br/>(last processed replay ID)
        PubSub->>Bus: Commit cursor position
        PubSub-->>Client: CommitReplayResponse (confirmed)
    end

    rect rgb(227, 242, 253)
        Note over Client,Bus: Publish Flow (bidirectional)
        Client->>PubSub: PublishRequest<br/>(Avro-encoded events)
        PubSub->>Bus: Write to event channel
        Bus-->>PubSub: Publish confirmation
        PubSub-->>Client: PublishResponse<br/>(replay IDs assigned)
    end

    Note over Client,PubSub: Connection stays open for continuous streaming
gRPC FeatureBenefit for Integration
HTTP/2 multiplexingMultiple streams over single connection — no connection overhead
Binary Avro encoding7-10x smaller payloads than JSON — lower bandwidth
Server-side cursorNo client-side replay ID management — simpler code
Pull-based deliveryClient controls pace — back-pressure built in
Bidirectional streamsPublish and subscribe on same connection

CTA board point

When recommending Pub/Sub API over CometD/Streaming API, highlight three things: (1) gRPC is 7-10x faster than REST/CometD, (2) managed subscriptions eliminate client-side replay ID management, and (3) Avro binary encoding reduces payload size significantly. CometD is in maintenance mode — all new implementations should use Pub/Sub API.


Event Bus Architecture

All Salesforce event technologies share the same underlying event bus infrastructure.

flowchart TB
    subgraph "Event Producers"
        DML[DML Operations<br/>Triggers, Flows]
        APEX_PUB[Apex EventBus.publish]
        API_PUB[REST API Publish]
        EXT_PUB[External gRPC Publish]
    end

    subgraph "Salesforce Event Bus"
        direction TB
        PE_CH[Platform Event Channels]
        CDC_CH[CDC Channels]
        CUSTOM_CH[Custom Channels]
    end

    subgraph "Event Consumers"
        APEX_SUB[Apex Triggers]
        FLOW_SUB[Flows]
        LWC_SUB[LWC Empiri API]
        COMET[CometD Clients<br/>Legacy]
        GRPC[Pub/Sub API<br/>gRPC Clients]
    end

    DML --> CDC_CH
    APEX_PUB --> PE_CH
    API_PUB --> PE_CH
    EXT_PUB --> PE_CH

    PE_CH --> APEX_SUB
    PE_CH --> FLOW_SUB
    PE_CH --> LWC_SUB
    PE_CH --> GRPC
    CDC_CH --> APEX_SUB
    CDC_CH --> FLOW_SUB
    CDC_CH --> LWC_SUB
    CDC_CH --> GRPC
    CDC_CH --> COMET

Replay Mechanism and Retention

Events are stored temporarily on the event bus with a replay ID. Subscribers can replay missed events within the retention window.

Event TypeRetention PeriodReplay Support
Platform Events (standard volume)24 hoursYes (replay ID)
Platform Events (high volume)72 hoursYes (replay ID)
Change Data Capture3 daysYes (replay ID)
Generic Streaming (legacy)NoneNo

Replay Positions

PositionBehavior
-1 (LATEST)Only receive new events from now
-2 (EARLIEST)Replay all events from beginning of retention window
Specific replay IDResume from a specific point

The 24-hour/72-hour trap

If your subscriber is down for longer than the retention period, those events are GONE. In CTA scenarios, always design for this: What is the recovery strategy if the subscriber misses events beyond the retention window? Options include: full data reconciliation job, alerting when subscriber lag exceeds threshold, or hybrid approach combining CDC with periodic batch sync.


Event-Driven Decision Flowchart

flowchart TD
    A[Need to react to changes<br/>or broadcast events?] --> B{What triggers the event?}

    B -->|Record data changes| C{Need to know<br/>which fields changed?}
    C -->|Yes| D[Change Data Capture]
    C -->|No| E{Custom semantics<br/>needed?}
    E -->|Yes| F[Platform Events]
    E -->|No| D

    B -->|Custom business event| F

    B -->|External system<br/>needs to publish| G{High throughput?}
    G -->|Yes| H[Pub/Sub API<br/>with Platform Events]
    G -->|No| I[REST API<br/>publish Platform Events]

    F --> J{Subscriber type?}
    D --> J
    J -->|Salesforce Apex/Flow| K[Apex Trigger or<br/>Record-Triggered Flow]
    J -->|Salesforce UI| L[LWC with<br/>Empiri API]
    J -->|External system| M{Performance needs?}
    M -->|Standard| N[CometD Client]
    M -->|High throughput| O[Pub/Sub API<br/>gRPC Client]

Anti-Patterns

Anti-PatternWhy It FailsBetter Approach
Using events for guaranteed deliveryAt-least-once is not exactly-onceDesign idempotent consumers, add reconciliation
Ignoring replay windowEvents lost after retention expiresMonitor subscriber lag, batch sync fallback
Polling instead of subscribingWastes API calls, higher latencySubscribe via Pub/Sub API or CDC
Publishing events on transaction rollbackCreates phantom eventsUse “Publish After Commit” behavior
Single subscriber bottleneckOne slow subscriber blocks processingScale subscribers independently, use DLQ

  • Data Quality & Governance — CDC event subscribers must handle data quality issues (missing fields, invalid formats) gracefully
  • Modern Platform Features — Platform Events and CDC are foundational to Agentforce, Flow orchestration, and modern event-driven platform capabilities
  • Sharing Model — event subscribers run in system context; understand how sharing rules apply to data accessed by event handlers

Sources