Salesforce

Salesforce Event-Driven Integration: Architecture Guide and Implementation

9 min read Salesforce 02 Nov 2026

Polling for changes every five minutes. Batch jobs that run overnight. APIs that check "did anything update?" dozens of times per second. These traditional integration patterns work, but they come with inherent limitations: latency, wasted resources, and scalability challenges.

Event-driven integration offers a fundamentally different approach. Instead of constantly asking "did something change?", systems react instantly when events occur. A record updates in Salesforce, and external systems receive a notification immediately.

This architectural shift matters because modern business operations increasingly demand real-time data. When a customer's order status changes, support teams need to know instantly. When a critical field updates, downstream systems must react immediately. When data changes in one system, five other systems need to stay synchronized without lag.

In this guide, we'll explore Salesforce event-driven integration architecture, covering Streaming API, Platform Events, and Change Data Capture. Drawing from real-world Salesforce integration services projects, you'll learn when to use each technology, how to implement them, and when event-driven architecture makes sense versus traditional approaches.

Understanding Event-Driven Architecture in Salesforce

Event-driven architecture is a design pattern where systems communicate through events rather than direct requests. When something significant happens, a record changes, a business process completes, a threshold is crossed, the system publishes an event. Other systems subscribe to these events and react accordingly.

How Traditional Integration Works

In traditional request-response integration, System A asks System B "do you have any updates for me?" repeatedly. Even when nothing has changed, the question gets asked. This polling approach wastes resources and introduces latency equal to your polling interval.

If you poll every 5 minutes, you accept up to 5 minutes of data lag. Poll more frequently to reduce lag, and you consume more API calls and system resources.

How Event-Driven Integration Works

In event-driven integration, System A doesn't ask questions. Instead, System B announces "something changed" the moment it happens. System A listens for these announcements and reacts instantly. No polling, no wasted calls, no unnecessary latency.

Why This Matters for Salesforce

Salesforce sits at the center of many organizations' operations. When data changes in Salesforce, other systems like ERP, marketing automation, analytics platforms, and custom applications often need to react. Event-driven integration ensures these reactions happen in real-time without exhausting API limits or adding infrastructure complexity.

Side-by-side Salesforce integration diagram comparing polling architecture with event-driven architecture

Salesforce Event-Driven Technologies: Three Options

Salesforce provides three primary technologies for event-driven integration. Each serves different use cases.

01

Streaming API (Generic Streaming)

Streaming API uses a push technology model based on CometD (Bayeux protocol) to send notifications when Salesforce records change. You define PushTopics that specify which objects and fields to monitor, and subscribers receive notifications whenever matching changes occur.

Best For

  • Monitoring standard Salesforce object changes
  • Real-time dashboards showing live Salesforce data
  • External systems that need immediate notification of record updates
  • Scenarios where you control both publisher and subscriber

Technical Characteristics

  • Uses PushTopic queries (SOQL-based)
  • Delivers notifications within 1-2 seconds of change
  • Payload includes changed field values
  • Supports field-level filtering
  • Limited to record create/update/delete events
02

Platform Events

Platform Events are custom-defined event messages you publish and subscribe to within Salesforce or from external systems. Unlike Streaming API, which monitors existing object changes, Platform Events let you define entirely custom event structures for business processes.

Best For

  • Custom business process events (not tied to standard object changes)
  • Complex event payloads with custom data structures
  • Scenarios where events don't map directly to record changes
  • Microservices architecture where systems publish custom notifications
  • Events that trigger both Salesforce and external system actions

Technical Characteristics

  • Define custom event schemas with specific fields
  • Publish events via Apex, Process Builder, Flow, or API
  • Subscribe via Apex Triggers, Flow, or external listeners
  • Events stored for 96 hours (High Volume) or 24 hours (standard)
  • Support for event replay (reprocess missed events)
03

Change Data Capture (CDC)

Change Data Capture automatically publishes change events for all creates, updates, deletes, and undeletes on specified objects. Unlike Streaming API's PushTopics, CDC captures all field changes without needing to define specific queries.

Best For

  • Data synchronization between Salesforce and external systems
  • Data warehousing and analytics replication
  • Scenarios requiring guaranteed delivery of all changes
  • Auditing and compliance tracking
  • When you need complete change history, not selective monitoring

Technical Characteristics

  • Captures all field changes automatically (no query definition)
  • Includes both new and old field values
  • Provides change event header with metadata (transaction info, origin)
  • Events available for 3 days with replay capability
  • More complete than Streaming API but requires more processing

When to Choose Event-Driven Integration

Event-driven architecture isn't always the right choice. Here's when it makes sense and when it doesn't.

Use Event-Driven Integration When:

You Need Real-Time Synchronization

When systems must stay synchronized with minimal latency, event-driven integration eliminates the delay inherent in polling. Customer status changes, inventory updates, or order modifications propagate instantly to all connected systems.

You're Approaching API Limits

Polling integrations consume API calls continuously, even when nothing changes. Event-driven integration uses API calls only when events occur, dramatically reducing consumption. Organizations polling multiple objects every minute can reduce API usage by 90% or more by switching to events.

You're Building Microservices Architecture

Microservices communicate through events by design. When your Salesforce integration is part of a larger microservices ecosystem, event-driven patterns align naturally with your architectural principles.

You Need to React to Complex Business Events

Sometimes you care about business events that don't map to single record changes a multi-step approval completing, a threshold being crossed, or a complex workflow finishing. Platform Events let you define and publish these custom business events.

Use Traditional Integration When:

You Need Historical Data Sync

Event-driven architecture handles real-time changes well but doesn't help with existing data. If you need to process records that changed yesterday or sync historical data, batch processes with Bulk API remain more efficient.

Event Volume is Unpredictable

If your event volume might spike dramatically and overwhelm subscribers, controlled batch processing provides better stability. Event-driven systems need capacity planning to handle peak loads.

Your Use Case is Truly Batch-Oriented

Some operations are inherently batch-oriented: nightly reports, weekly data exports, monthly reconciliations. Forcing these into event-driven patterns adds complexity without benefit.

You Need Guaranteed Sequential Processing

Events can arrive out of order, especially under load. If sequence matters critically, batch processing with controlled ordering may be more reliable.

Implementing Streaming API for Real-Time Object Monitoring

Let's walk through implementing Streaming API to monitor Salesforce record changes in real-time.

Step 1: Create a PushTopic

PushTopics define what changes to monitor. Here's an example monitoring Account changes:

// Create PushTopic in Salesforce (via Developer Console or Apex)
PushTopic pushTopic = new PushTopic();
pushTopic.Name = 'AccountUpdates';
pushTopic.Query = 'SELECT Id, Name, Industry, AnnualRevenue FROM Account WHERE Industry != null';
pushTopic.ApiVersion = 65.0;
pushTopic.NotifyForOperationCreate = true;
pushTopic.NotifyForOperationUpdate = true;
pushTopic.NotifyForOperationDelete = false;
pushTopic.NotifyForOperationUndelete = false;
pushTopic.NotifyForFields = 'Referenced'; // Only notify if queried fields change

insert pushTopic;

PushTopic Configuration Options:

  • NotifyForFields = 'All': Notify for any field change on the object
  • NotifyForFields = 'Referenced': Only notify if fields in SELECT clause change
  • NotifyForFields = 'Select': Only notify if fields in WHERE clause change
  • NotifyForFields = 'Where': Combination of Referenced and Select
Step 2: Subscribe to Events (External System)

Here's a Node.js subscriber using the Faye library (CometD implementation):

const faye = require('faye');
const jsforce = require('jsforce');

// Authenticate with Salesforce
const conn = new jsforce.Connection({
  loginUrl: 'https://login.salesforce.com'
});

await conn.login(username, password);

// Create CometD client
const client = new faye.Client(
  `${conn.instanceUrl}/cometd/65.0/`,
  { timeout: 120 }
);

// Add authentication extension
client.addExtension({
  outgoing: (message, callback) => {
    message.ext = message.ext || {};
    message.ext.replay = true; // Enable event replay

    if (message.channel === '/meta/handshake') {
      message.ext.authorization = `Bearer ${conn.accessToken}`;
    }

    callback(message);
  }
});

// Subscribe to PushTopic
const subscription = client.subscribe(
  '/topic/AccountUpdates',
  (message) => {
    console.log('Received event:', message);

    // Event payload structure
    const event = message.data.event;
    const sobject = message.data.sobject;

    // React to the change
    handleAccountUpdate(sobject);
  }
);

// Handle errors
subscription.then(
  () => console.log('Subscribed to AccountUpdates'),
  (error) => console.error('Subscription failed:', error)
);

// Process the received data
const handleAccountUpdate = (account) => {
  console.log(`Account ${account.Id} updated:`);
  console.log(`  Name: ${account.Name}`);
  console.log(`  Industry: ${account.Industry}`);
  console.log(`  Revenue: ${account.AnnualRevenue}`);

  // Update external system
  syncToExternalSystem(account);
};
Step 3: Implement Event Replay

Streaming API supports event replay, allowing subscribers to retrieve missed events:

// Store replay ID after processing each event
let lastReplayId = -1; // -1 means get all available events

client.addExtension({
  outgoing: (message, callback) => {
    if (message.channel === '/meta/subscribe') {
      message.ext = message.ext || {};
      message.ext.replay = {
        '/topic/AccountUpdates': lastReplayId
      };
    }
    callback(message);
  }
});

// Update replay ID when receiving events
client.subscribe('/topic/AccountUpdates', (message) => {
  lastReplayId = message.event.replayId;

  // Store this ID persistently so recovery works after restarts
  saveReplayId(lastReplayId);

  handleAccountUpdate(message.data.sobject);
});

Implementing Platform Events for Custom Business Events

Platform Events shine when you need custom event structures beyond standard object changes.

Step 1: Define Platform Event

Create a Platform Event in Salesforce Setup:

  • Object: Order_Shipped__e
  • Fields:
  • Order_Number__c (Text, 50)
  • Customer_Email__c (Email)
  • Tracking_Number__c (Text, 100)
  • Shipping_Method__c (Picklist)
  • Estimated_Delivery__c (Date)
Step 2: Publish Events

From Apex:

// Publish event when order ships
public static void notifyOrderShipped(String orderId) {
    Order order = [SELECT OrderNumber, Customer__r.Email, Tracking_Number__c,
                   Shipping_Method__c, Estimated_Delivery__c
                   FROM Order WHERE Id = :orderId];

    // Create event
    Order_Shipped__e event = new Order_Shipped__e(
        Order_Number__c = order.OrderNumber,
        Customer_Email__c = order.Customer__r.Email,
        Tracking_Number__c = order.Tracking_Number__c,
        Shipping_Method__c = order.Shipping_Method__c,
        Estimated_Delivery__c = order.Estimated_Delivery__c
    );

    // Publish event
    EventBus.publish(event);
}

From REST API:

// External system publishes event to Salesforce
const publishEvent = async (eventData) => {
  const response = await fetch(
    `${instanceUrl}/services/data/v65.0/sobjects/Order_Shipped__e/`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(eventData)
    }
  );

  return await response.json();
};

// Usage
await publishEvent({
  Order_Number__c: 'ORD-12345',
  Customer_Email__c: '[email protected]',
  Tracking_Number__c: '1Z999AA10123456784',
  Shipping_Method__c: 'Express',
  Estimated_Delivery__c: '2025-06-15'
});
Step 3: Subscribe to Platform Events

Internal Subscriber (Apex Trigger):

trigger OrderShippedSubscriber on Order_Shipped__e (after insert) {
    List<Task> followUpTasks = new List<Task>();

    for (Order_Shipped__e event : Trigger.New) {
        // Create follow-up task for account manager
        Task task = new Task(
            Subject = 'Order ' + event.Order_Number__c + ' shipped',
            Description = 'Order shipped via ' + event.Shipping_Method__c +
                          '. Tracking: ' + event.Tracking_Number__c,
            Priority = 'Normal',
            Status = 'Not Started',
            ActivityDate = event.Estimated_Delivery__c
        );

        followUpTasks.add(task);
    }

    if (!followUpTasks.isEmpty()) {
        insert followUpTasks;
    }
}

External Subscriber (Node.js):

// Subscribe to Platform Events from external system
client.subscribe('/event/Order_Shipped__e', (message) => {
  const event = message.data.payload;

  console.log(`Order ${event.Order_Number__c} shipped`);

  // Send customer notification email
  sendShippingNotificationEmail({
    to: event.Customer_Email__c,
    orderNumber: event.Order_Number__c,
    trackingNumber: event.Tracking_Number__c,
    estimatedDelivery: event.Estimated_Delivery__c
  });

  // Update external order tracking system
  updateOrderTrackingSystem({
    orderNumber: event.Order_Number__c,
    status: 'SHIPPED',
    trackingNumber: event.Tracking_Number__c
  });
});

Implementing Change Data Capture for Complete Data Sync

Change Data Capture provides the most comprehensive event stream for data synchronization scenarios.

Step 1: Enable CDC for Objects

In Salesforce Setup → Change Data Capture → Select objects to enable:

  • Account
  • Contact
  • Opportunity
  • Custom Objects
Step 2: Subscribe to Change Events
// Subscribe to Account change events
client.subscribe('/data/AccountChangeEvent', (message) => {
  const changeEvent = message.data.payload;
  const header = changeEvent.ChangeEventHeader;

  console.log('Change Type:', header.changeType); // CREATE, UPDATE, DELETE, UNDELETE
  console.log('Changed Fields:', header.changedFields);
  console.log('Record IDs:', header.recordIds);

  // Process based on change type
  switch (header.changeType) {
    case 'CREATE':
      handleAccountCreated(changeEvent);
      break;
    case 'UPDATE':
      handleAccountUpdated(changeEvent, header.changedFields);
      break;
    case 'DELETE':
      handleAccountDeleted(header.recordIds);
      break;
  }
});

const handleAccountUpdated = (event, changedFields) => {
  // CDC provides both old and new values for changed fields
  console.log('Account ID:', event.Id);

  changedFields.forEach(field => {
    console.log(`${field} changed:`);
    console.log(`  Old value: ${event[field]}`);
    // New value is in the main event payload
  });

  // Sync to data warehouse
  syncToDataWarehouse({
    table: 'accounts',
    operation: 'UPDATE',
    recordId: event.Id,
    changes: changedFields.reduce((acc, field) => {
      acc[field] = event[field];
      return acc;
    }, {})
  });
};

Common Implementation Scenarios for Event-Driven Integration

Here are typical scenarios where Salesforce event-driven integration delivers value:

Scenario 1

Real-Time Dashboard Updates

Challenge

A sales operations dashboard shows live pipeline data but polling every minute creates performance issues and API consumption concerns.

Solution

Implement Streaming API PushTopic monitoring Opportunity changes. Dashboard subscribes to events and updates in real-time as opportunities progress through stages.

Result: Dashboard updates within 1-2 seconds of changes. API consumption drops by 95% compared to minute-by-minute polling.
Scenario 2

Multi-System Order Processing

Challenge

When an order is created in Salesforce, five external systems need to react: inventory, shipping, billing, customer communication, and analytics. Polling each system independently creates delays and complexity.

Solution

Publish a custom Platform Event (Order_Created__e) when orders are created. Each external system subscribes to this event and reacts independently.

Result: All systems process orders within seconds. Decoupled architecture allows each system to fail and retry independently without affecting others.
Scenario 3

Data Warehouse Synchronization

Challenge

Analytics team needs complete, real-time Salesforce data replica in their data warehouse. Nightly batch loads create 24-hour data lag.

Solution

Enable Change Data Capture for all relevant objects. Data pipeline subscribes to change events and applies them to warehouse tables in real-time.

Result: Data warehouse stays synchronized with Salesforce continuously. Analytics dashboards show real-time business metrics instead of yesterday's data.
Scenario 4

Customer Service Notifications

Challenge

Support agents need instant notification when VIP customer cases are created or escalated, but email alerts alone don't provide sufficient visibility.

Solution

Configure Platform Events published when VIP cases are created. External notification service subscribes and sends push notifications to support managers' mobile devices.

Result: VIP cases receive immediate attention. Response times improve significantly for high-priority customers.

Handling Common Challenges

Challenge 1

Event Ordering

Problem: Events may arrive out of order, especially under high load. If processing order A before order B matters, you need explicit handling.

Solution: Include sequence numbers or timestamps in event payloads. Implement buffering and ordering logic in subscribers:

const eventBuffer = [];
let lastProcessedSequence = 0;

const processOrderedEvent = (event) => {
  eventBuffer.push(event);
  eventBuffer.sort((a, b) => a.sequence - b.sequence);

  // Process all events in sequence
  while (eventBuffer.length > 0 &&
         eventBuffer[0].sequence === lastProcessedSequence + 1) {
    const nextEvent = eventBuffer.shift();
    handleEvent(nextEvent);
    lastProcessedSequence = nextEvent.sequence;
  }
};

Challenge 2

Duplicate Event Delivery

Problem: Distributed systems occasionally deliver events multiple times. Subscribers must handle duplicates gracefully.

Solution: Implement idempotent processing using event IDs:

const processedEvents = new Set();

const handleEvent = (event) => {
  const eventId = event.replayId || event.eventUuid;

  // Skip if already processed
  if (processedEvents.has(eventId)) {
    console.log('Duplicate event detected, skipping');
    return;
  }

  // Process event
  processEvent(event);

  // Mark as processed
  processedEvents.add(eventId);

  // Persist processed IDs to survive restarts
  persistProcessedId(eventId);
};

Challenge 3

Subscriber Failures

Problem: If your subscriber crashes or disconnects, you miss events.

Solution: Implement event replay using stored replay IDs:

// On startup, load last processed replay ID
const startupReplayId = await loadLastReplayId();

client.subscribe('/topic/Updates', {
  replayId: startupReplayId // Resume from last processed event
}, (message) => {
  handleEvent(message);

  // Save replay ID after successful processing
  saveReplayId(message.event.replayId);
});

Challenge 4

High Event Volume

Problem: Peak periods generate thousands of events per second, overwhelming subscribers.

Solution: Implement batching and backpressure:

const eventQueue = [];
const BATCH_SIZE = 100;
const PROCESS_INTERVAL = 5000; // 5 seconds

// Buffer events
client.subscribe('/event/HighVolume__e', (message) => {
  eventQueue.push(message.data.payload);
});

// Process in batches
setInterval(() => {
  if (eventQueue.length === 0) return;

  const batch = eventQueue.splice(0, BATCH_SIZE);
  processBatch(batch);
}, PROCESS_INTERVAL);

When Salesforce Event-Driven Integration Makes Sense

Use this decision framework to evaluate whether event-driven architecture fits your use case.

Choose Event-Driven When:

  • Latency requirements are seconds, not minutes or hours
  • Systems must react immediately to changes
  • You're approaching API limits with polling
  • Event volume is manageable (under 100,000/day for most implementations)
  • You need loose coupling between systems
  • Multiple systems must react to the same changes

Choose Batch Processing When:

  • Latency requirements are hours or days
  • Operations are naturally batch-oriented (reports, reconciliation)
  • Event volume is extremely high and sustained
  • You need guaranteed sequential processing
  • Historical data processing is the primary use case

Consider Hybrid Approaches When:

  • Some changes need real-time handling, others don't
  • Event volume varies dramatically (real-time during business hours, batch overnight)
  • You need both real-time notifications and historical data sync

Getting Started with Salesforce Event-Driven Integration

Salesforce event-driven integration transforms how systems communicate. It replaces polling delays with instant reactions, reducing API consumption, and enabling real-time business operations.

Whether you choose Streaming API for monitoring object changes, Platform Events for custom business events, or Change Data Capture for complete data synchronization, the architectural principles remain consistent: publish events when significant changes occur, subscribe to relevant events, and react appropriately.

The key to successful implementation is matching the right technology to your use case, implementing robust error handling and replay logic, and designing for the operational realities of distributed event-driven systems.

Ready to implement event-driven architecture in your Salesforce integrations? Our Salesforce integration services team designs and implements event-driven solutions that scale with your business needs.

Talk to Expert