Streaming and Real-Time: The Five-Second Abandoned Cart

"Streaming" and "real-time" are different products with different latencies — and mixing them up sinks projects. An e-commerce build that reacts to live web behavior in seconds.

The scenario

Northbay Goods — the e-commerce retailer from our data actions build — has the classic conversion leak: a shopper loads a cart, reaches checkout, hesitates at the shipping cost, and leaves. The recovery email arrives the next morning; by then the shoes were bought elsewhere.

The requirement from the growth team: "When a signed-in customer abandons checkout, open a proactive chat with our agent — with the cart contents and an incentive decision — while they're still on the site." That's a seconds-scale loop: event in, profile updated, decision made, agent engaged.

Northbay's team assumed their existing "streaming" ingestion had this covered. It didn't — and understanding why is the most valuable part of this build. This post assumes the fundamentals series; the batch-side wiring (data actions → platform events → Apex) is in that post and gets reused here.

Three speeds, and the trap between them

Data 360 has three distinct freshness tiers. The names sound interchangeable. The latencies are not:

TierHow data arrivesRealistic latencyRight for
BatchScheduled connector refreshesHours to a dayHistory, finance data, most CIs
Streaming ingestionIngestion API streaming — fire-and-forget micro-batches, processed asynchronouslyMinutesOrder status, IoT telemetry, near-real-time dashboards
Real-time layerWeb SDK / Mobile SDK / server-to-server into the sub-second profileSub-second — the large majority of events land well under a second end to endIn-session personalization, live agent context

The trap: streaming ingestion accepts events instantly (a 202 Accepted in milliseconds) but processes them in micro-batches on a minutes cadence. Northbay's original design streamed cart events and expected instant reactions — the acceptance latency fooled them. For a next-morning email, minutes are fine. For "while they're still on the site," only the real-time layer closes the loop.

Capturing the events

For the storefront, the natural capture path is the Web SDK: it ships page, cart and checkout interactions from the browser into the real-time pipeline, with a schema you define per event type. Northbay tracks cart_update and checkout_step events keyed by the signed-in customer ID.

Their order-management system also participates server-side through the Ingestion API. The streaming pattern is a plain REST POST of a JSON envelope against a source and object you configured on the Ingestion API connector:

POST /api/v1/ingest/sources/Web_Store/CartEvent
Authorization: Bearer {data360_token}
Content-Type: application/json

{
  "data": [
    {
      "event_id": "ce-20260717-88412",
      "customer_id": "CUST-004471",
      "event_type": "checkout_abandoned",
      "cart_value": 182.50,
      "item_count": 3,
      "event_time": "2026-07-17T14:22:05Z"
    }
  ]
}

Production notes that save debugging time: the payload must match the connector's declared schema exactly, stay under the 200 KB limit, and a 202 means accepted, not processed — build your monitoring on data arriving in the DLO, not on HTTP status codes.

The real-time profile: where the pieces from this series meet

Sub-second data is useless if the rest of the pipeline runs overnight. The real-time layer runs fast versions of the machinery you already know:

  • Real-time identity: the web event carries the signed-in customer ID, which resolves to the same unified profile your identity resolution rules maintain — so the live session and the historical profile are one person, immediately.
  • Real-time data graphs: the sub-second profile updates a real-time data graph, so the cart state is readable through the same lookup API pattern from the data graphs post — the agent asks for the document and gets the cart the customer abandoned seconds ago.
  • Streaming insights: a windowed metric over the event stream — Northbay computes checkout reached, no purchase event within 15 minutes, cart value above 100 — the real-time sibling of the batch CIs from the Calculated Insights build.

Closing the loop: from signal to agent in seconds

The action side reuses the architecture from the data actions build, at higher speed: a data action on the streaming signal publishes a platform event, and the org reacts. Northbay's event mirrors their churn one:

trigger CartAbandoned on Cart_Abandoned__e (after insert) {
    CartRecoveryService.startRecovery(Trigger.new);
}
public with sharing class CartRecoveryService {

    public static void startRecovery(List<Cart_Abandoned__e> events) {
        List<MessagingSession> toRoute = new List<MessagingSession>();
        Set<String> customerIds = new Set<String>();
        for (Cart_Abandoned__e evt : events) {
            customerIds.add(evt.Customer_Id__c);
        }

        // Guard: one recovery attempt per customer per day
        Set<String> recentlyContacted = new Set<String>();
        for (Cart_Recovery_Attempt__c prior : [
            SELECT Customer_Id__c FROM Cart_Recovery_Attempt__c
            WHERE Customer_Id__c IN :customerIds
              AND CreatedDate = TODAY
        ]) {
            recentlyContacted.add(prior.Customer_Id__c);
        }

        List<Cart_Recovery_Attempt__c> attempts =
            new List<Cart_Recovery_Attempt__c>();
        for (Cart_Abandoned__e evt : events) {
            if (recentlyContacted.contains(evt.Customer_Id__c)) { continue; }
            recentlyContacted.add(evt.Customer_Id__c);
            attempts.add(new Cart_Recovery_Attempt__c(
                Customer_Id__c = evt.Customer_Id__c,
                Cart_Value__c  = evt.Cart_Value__c,
                Channel__c     = 'Proactive chat'
            ));
        }
        if (!attempts.isEmpty()) {
            insert attempts;
        }
        // The proactive chat itself is launched by a record-triggered
        // flow on Cart_Recovery_Attempt__c, which invokes the messaging
        // channel with the agent and passes the cart context.
    }
}

The recovery-attempt record is doing two jobs: it's the frequency-cap guard (the same idempotency discipline as the churn build — real-time signals fire more often, so the guard matters more), and it's the audit trail the growth team measures against. The agent that picks up the conversation reads the cart through the real-time data graph and applies the incentive policy — with the guardrails any write-capable agent needs (governed agent actions).

End-to-end: browser event → real-time profile → streaming signal → platform event → proactive agent chat, in single-digit seconds — against the next-morning email it replaced.

What real-time should cost you

The real-time layer is premium capacity, and the fastest tier should carry the least data. Northbay's rules:

  • Real-time only for in-session moments. Cart abandonment and live agent context qualify. Churn scoring stays nightly-batch (Part 2) — a weeks-scale signal gains nothing from millisecond delivery.
  • Slim events. The web event carries IDs, amounts and types — not product catalogs. Anything the agent needs beyond that, it reads from the graph at conversation time.
  • Cap the blast radius. The streaming signal's conditions (cart value, signed-in only, once per day) live in the insight and the Apex guard — tightening them is a config change, not a re-architecture. Facts in the stream, judgment in the thresholds: the same separation this series has used since Part 2.

What you learned

  • Batch, streaming ingestion and the real-time layer are three tiers with different latencies — streaming's instant 202 is acceptance, not processing.
  • The Web SDK feeds the sub-second profile from the browser; the Ingestion API streams server-side events as schema-matched JSON envelopes under 200 KB.
  • Real-time identity and real-time data graphs make the live session and the historical profile one readable document.
  • The action loop is the same data-action → platform-event → Apex pattern as batch, with idempotency guards promoted from good practice to hard requirement.
  • Put only genuinely conversational moments on the real-time tier; everything else is cheaper one tier down.

That completes the advanced series. The full track — five fundamentals builds and four advanced deep dives — lives on the Data 360 page.

Sources: Data 360 Integration Guide — Ingestion API · Data 360 Ingestion API Reference — Real-Time Ingestion · Streaming Ingestion Walkthrough