Best practices for real-time data streaming in Salesforce Data Cloud
Stream the events a person is waiting on. Batch the history. Streaming every row is a bill, not an architecture.
Data & IntegrationA service agent is on the phone. The case status changed in the source system a few minutes ago. The stream that was meant to carry that status is also carrying every profile edit in the org, so the meter is moving and the agent is still looking at yesterday. A corrected email arrived on the same stream an hour later and now sits beside the original. Nothing has chosen between them.
Call the product by its name
Search traffic still says Data Cloud. The product name is Data 360. Salesforce rebranded it on 14 October 2025. The behaviour is unchanged. During the transition you will still see Data Cloud in the application and in the documentation. That is a label. It is not a second platform with different streaming rules. The help page puts it in one sentence you should keep: "While the name is new, the functionality and content remains unchanged."
The same help page describes one job that accepts streaming and batch data: ingest it, harmonise it, unify it, and analyse it. Both paths are real. Neither path is a principle. A stream is a freshness promise to a named waiter. A batch is a reconciliation promise you can rerun. Write the promise down before anyone enables a connector. If the sentence names no waiter and no window, you are not designing. You are copying a source system into a meter.
Stream only what someone is waiting on
Name the person or the process that cannot take the next step without the event. A service agent waiting on a status. An activation that must stop when consent is withdrawn. A segment that has to see a session event before the session ends. If you cannot name that waiter, do not stream the object. Put it on the batch.
The waiter is a role in a moment, not a department. "Marketing wants it real time" names a building. The waiter is the journey step that must suppress a send when a flag flips, or the screen a person reads before a call ends. If the next step still happens on a human timetable of hours, the event is not waiting on a stream. Someone will look in the morning. Morning is a batch.
Send the fields the waiter actually reads. Leave the rest of the record on the load that already carries the full row. A wide event is easy to approve in a workshop. It is hard to remove once a screen depends on a column that nobody reads. Freshness is the requirement. A second copy of history is a different requirement, and it is usually the expensive one.
Keep a short register: event name, waiter, fields, and the delay they will tolerate. Review it when someone asks for the same stream, plus a few columns. Those columns are how a narrow event becomes a permanent feed. Add a column only when the waiter will read it. A column added for the analysts is a second consumer with no freshness requirement. It belongs on the batch those analysts already trust.
The delay has to be a number you can say out loud. "As fresh as possible" is not a number. A service status might be a few minutes. A consent withdrawal that governs live spend might be a few minutes. A profile attribute used in a weekly segment is a day, and a day is a batch. If two waiters disagree about the delay, you have two requirements. The slower one does not get to ride the faster path for free.
Put history on a schedule
Orders, cases, campaign responses, and profile attributes that nobody is watching this minute belong in a batch. Run it on a cadence you can say out loud. Nightly is a design. "Whenever the source emits" is the source's timetable, not yours.
Let identity resolution run against that same cadence, so the unified profile moves when the history moves. Identity resolution is the processing engine that generates unified profiles from source profile data stored in Data 360. A nightly load of profile attributes is a design you can operate. A stream of those same attributes, fired only because the source emits them, is a second path and a larger bill. The engine does not become more correct because a row arrived in seconds. A fast ingest of a blank key is a blank key that arrived quickly.
Unified profiles are keys back to the source records. They are not a golden record. Identity resolution does not pick a winning value and does not override source values. Two emails that both streamed in remain two emails, on the records you stored. The profile points at both. If you streamed a correction and left the original event in place, you now have two assertions and no survivor. Streaming did not create a merge. It created a race.
A stream is a poor place to repent. Give the scheduled load permission to land the correction: a fixed email, a late order, a consent flag repaired in the system of record. If the source will revise rows, say so in the design, and do not pretend the first event was final. Name who reruns the load, which key identifies the row, and what a deletion in the source does to the copy. Those three notes are the difference between a batch you can trust and a pile of events you are afraid to touch.
The choices under this are the ones that get expensive after the first connector runs. What "unified" means for this waiter, which attributes that waiter needs, and whether the object is copied or only referenced, belong in writing first. The longer list is in getting Data 360 right the first time.
A stream of everything is a bill
Both paths are documented. A reason to put every object on the fast path is not. Each streamed row is processed. Processing sits with usage. Some Data 360 features are offered as add-on licences, and other features have usage limits, many of which can be adjusted to the business. An adjustment is a commercial event. It is not a checkbox you flip because a connector screen offered it.
Before you enable a stream, name the meter it moves and the person who reads that meter each month. If nobody owns the meter, nobody owns the stream. "The licence covers it" is the sentence that produces the surprise in month two. The licence is the opening line. The stream is the consumption. How to separate those lines, without inventing a price, is the subject of the total cost of ownership.
Ship one streaming use case, with an owner, before you design the second. If the first has no waiter and no check on freshness, turn it off. The architecture is the set of paths you can still explain after the build team has gone. Anything you cannot explain in that meeting is a candidate to batch, or to drop.
What people substitute for a stream
Three substitutions show up in the same workshop. None of them is a waiter.
Zero copy is federation. The help page says you can connect data using zero copy data federation. The external store keeps the bytes. That is a statement about where the data lives, not about how fast a person on the phone will see it. Zero copy is not a latency promise. A federated table does not become real time because you avoided a copy. If someone is waiting, measure the path you actually turned on, with the query you actually run. Until that test exists, you have a pattern. You do not have a freshness number, and you should not brief one.
Tableau Next does not replace Tableau. The help page says you can expand Data 360 using Tableau or Tableau Next. The "or" is the word to keep. A chart of a streamed object is still a chart of whatever you stored. Moving that chart to a new surface does not create a waiter, and it does not make a nightly attribute live. The title of the chart should say whether the figure was streamed or batched. A reader who cannot tell those apart will brief a live number that was loaded overnight.
The third substitution is a lake that emits files all day. The lake's cadence is not your waiter's cadence. If nobody in the CRM is blocked until the next file lands, the file is history. History belongs on a schedule you can rerun. Streaming it because the bucket is busy is how a storage decision becomes a processing bill, with no one on the phone any better informed.
Two paths for one attribute
Pick one arrival path per attribute unless you have written, in a sentence, how a correction beats the earlier value. The failure is ordinary. Email loads nightly from the CRM. A stream also emits email on every edit, because the connector could. For a day the two disagree. Identity resolution points at both, because it does not override source values and it does not crown a survivor. The profile looks fuller. It is less usable. A service agent now has two addresses and no rule.
The sentence you need is small. "Email arrives on the nightly batch. The stream may carry a consent withdrawal, and nothing else from this object." That sentence stops the race. It also stops the workshop habit of ticking every channel the screen offers. A channel without a sentence is not a design. It is a default.
The same discipline applies when the source revises a key rather than an attribute. A migration that reissues customer numbers will make yesterday's people look new if the stream treats every identifier as a birth. Batch the identifier, keep the old key on the row long enough to reconcile, and do not let a stream of new ids become a second population. Identity resolution will faithfully relate whatever keys you stored. It will not notice that Tuesday's identifier was a reissue of Monday's.
The register is the design
Write one row per streamed event. Five columns are enough: the event, the waiter, the fields, the delay, and the person who reads the meter. Review the register when a new source is proposed. A new source is the moment a narrow stream grows columns, because the new source brings new fields and someone will ask to "include them while we are here."
Promotion from batch to stream is allowed. It requires a waiter who was not there last quarter, a delay, and a check that the key on the event is populated. A fast blank is still a blank. Demotion is also allowed. If the waiter left, or the activation moved to a nightly run, the stream is theatre. Turn it off in the same week you notice. Leaving it "in case we need it" is how the bill survives the requirement.
| Path | Use it when | It promises | It does not promise |
|---|---|---|---|
| Stream | A named person or process stalls without the event | Freshness inside a delay you wrote down | A cleaner profile, a lower bill, or a correction |
| Batch | History, profile attributes, and repairs | A load you can rerun and reconcile | That someone on a live call will see this row |
| Zero copy federation | The external store should keep the bytes | The store stays in charge of the bytes | A latency figure, or a substitute for a stream |
| Tableau or Tableau Next | The asker already works in that tool | A view of what Data 360 holds | That Tableau Next replaces Tableau |
Read the third column in the design review, not the first. Teams approve a path and skip the promise. The promise is the only cell a waiter can test on a Thursday.
Where it fails early
The connector demo becomes the design. Someone enables streaming on the object the demo used, usually the widest object in the room. The demo had no waiter. Production inherits the demo. By the time a service agent complains, a screen depends on a column, and removing the stream is a project rather than a setting.
Freshness theatre. The slide says real time. The activation still runs overnight. The stream is paying for a freshness nobody reads. Either name the step that reads the event before the window closes, or turn the stream off. A label on a slide is not a consumer.
History smuggled into the event. The waiter needed a status. The payload also carries the last fifty attributes "so the screen can render." The screen could have read those attributes from the batch profile. You have now tied a wide, slow-changing record to a fast path, and every future column request will cite the precedent.
No replay. The first week is fine. The first correction is not. A late order, a merged CRM contact, a consent flag fixed by a person: none of them have a path back except "emit another event and hope." Hope is not an operator. The batch rerun is.
The first stream worth keeping
Pick one event a named person is already waiting on. Write the five columns. Count blanks on the key before you celebrate the speed. Run identity resolution on the cadence of the batch that holds the profile, unless the waiter is the profile itself and you have said so in the register. Watch one test from the source change to the screen or the segment.



