Data 360
Salesforce Connect or Data 360 zero copy: which way to reach external data
Both let you use data that lives in another system without copying it into Salesforce, and they solve completely different problems. This is the decision: when external objects are the right answer, when Data 360 zero copy is, and when you should just ingest the data after all.
An architect asked me last month why their agent kept timing out on a customer’s order history. The orders lived in SAP. Someone had exposed them as external objects through Salesforce Connect, wired an agent action to query them, and the whole thing fell over the first time a service rep asked about a customer with two thousand orders.
The fix was not a bigger timeout. It was that external objects were the wrong tool for what they were doing. They wanted to ground an agent on order history at scale, which is a Data 360 job. They had built a real-time operational lookup instead.
Both features let you work with data that never lands in your org. That shared headline hides two products aimed at different problems, and picking the wrong one shows up as a timeout, a credit bill, or a report that won’t build. Here is how I decide.
The one-line version
Use Salesforce Connect and external objects when a person or a Flow needs to see a specific external row inside the CRM, live, and behaving like a record. Use Data 360 zero copy when you need external data at analytical scale, for segmentation, calculated insights, identity resolution, or grounding an agent. When you need triggers, roll-ups, or heavy write-back, neither is right and you should copy the data in.
Those are different jobs. External objects are a transactional window. Zero copy is an analytical bridge. The rest of this is what happens when you push each one past what it is for.
What Salesforce Connect gives you
Salesforce Connect maps an external table to an external object, whose API name ends in __x instead of __c. It reads through an adapter: the OData 2.0 and 4.0 adapters for anything that speaks OData, a cross-org adapter for another Salesforce org, or a custom adapter you write against the Apex Connector Framework.
Once mapped, the external object looks like a real object in most of the UI. You get list views, it shows in global search, you can put a related list of external rows on an Account page, and you can reference it from a Flow. No row is stored. Every read is a live callout to the source system at the moment someone opens the page.
That last sentence is the whole product, and the whole risk. The data is always current because there is no copy. The page is only as fast and as available as the source, because there is no copy.
The limits that decide whether external objects fit
The general limits for Salesforce Connect rule out a lot of designs before you write anything.
You can define up to 200 external objects per org, and they don’t count against your custom-object allocation. Each SOQL query can span at most four joins across external objects and other objects. You cannot use aggregate functions on external objects: no SUM(), AVG(), MIN(), MAX(), GROUP BY, or HAVING, and COUNT() is restricted. So the “total order value for this account” number you wanted is not something the query can compute.
External objects don’t fire triggers. They don’t support roll-up summary fields or formula fields. If your design needs any of those, the data has to be inside Salesforce, and external objects are not the answer.
For relationships, you get an external lookup when the external rows carry Salesforce IDs, and an indirect lookup when they don’t. Indirect lookups match a unique external ID field on a standard or custom parent against a field on the external child, which is how you hang SAP orders off the right Account without SAP knowing any Salesforce IDs.
On volume: turn on the High Data Volume option for large external datasets and the source stops needing to support paging the way reports expect, but with High Data Volume on you lose some features, reporting among them. That trade is the one that bit the team I opened with. They had a high-volume source and wanted both fast lookups and reports, and you don’t get both.
Callouts are the other ceiling. The OData adapters don’t have a Salesforce-imposed per-call cap, but Salesforce monitors an hourly OData callout threshold and Developer Edition is capped at 1,000 calls an hour. In practice the source system’s own rate limits bind first. Every list view refresh, every report run, every agent action is a live call, and they add up faster than anyone estimates.
What Data 360 zero copy is for instead
Zero copy in Data 360 is a different mechanism with a similar promise. Instead of a row-by-row callout for the UI, it registers an external warehouse table as a data lake object and runs federated queries against it. Query federation is supported for Snowflake, Google BigQuery, Amazon Redshift, and Databricks, over JDBC, with Data 360 pushing down the parts of the query the warehouse can compute.
The data is processed in memory and not stored in Data 360. From there it behaves like any other Data 360 object: you map it to a data model object, unify it, build segments on it, drive calculated insights, or point a retriever at it to ground an agent. That is the scale external objects can’t reach, because you are borrowing the warehouse’s compute instead of paging rows through a callout.
The cost model is different too, and worth stating plainly. Live federation runs compute on the external warehouse, so you pay Snowflake or BigQuery for the query, and you pay Data 360 for its own processing and per-row data transfer. If the warehouse is down, the data is down; federation has no local fallback. For interactive dashboards you can turn on acceleration, which caches selected data inside Data 360 on a schedule, and now you are paying to store part of a copy. The “no pipelines” pitch is real, but the bill has more lines than the slide suggests. I wrote up what moves and what it costs separately.
The important architectural point: zero copy does not put a row on an Account page for a rep to read in the moment. It puts external data into the analytical and AI layer. Different job.
Reading the same SAP orders both ways
Take the order-history example and run it through both.
As external objects: a rep opens an Account, sees a related list of recent orders pulled live from SAP, clicks one, and sees today’s status. Good for a rep working one account. It falls apart when an agent needs to reason over two thousand orders, or when finance wants a report summing order value across a segment, because the aggregate isn’t allowed and the volume overruns the callout.
As zero copy: the SAP orders (or the warehouse they land in) register as a data lake object, unify onto the customer profile, and feed a segment or an agent retriever. Good for “customers with more than $50k of orders in the last year” and for grounding an agent on order history. Useless for the rep who wants to click into one live order and see whether it shipped this morning, because you are querying a federated snapshot, not the live SAP row.
Same data, opposite tools, and the choice is entirely about who reads it and why. If you need both, you build both, and that is a legitimate answer.
When the honest move is to copy the data
There is a third option people skip because zero-anything sounds cleaner: bring the data in. If you need triggers on the external records, roll-up summaries, formula fields, offline availability, or write-heavy transactional joins, no federation gets you there. Ingest it through an integration pattern that survives production, or stream it into Data 360 as a native data stream, and accept the copy.
The reflex to avoid copying is usually about storage cost or staleness. Both are solvable. A design that fights the platform to avoid a copy it needs is more expensive than the copy, every time.
How I choose in five questions
Walk these in order and you rarely land wrong.
- Does a human or a Flow need to see or act on a specific external row, live, inside the CRM? If yes, external objects.
- Is the volume per interaction small, tens of rows, not thousands? External objects hold up. Thousands, and they don’t.
- Do you need aggregates, segmentation, identity resolution, or agent grounding across the external data? That is Data 360 zero copy.
- Do you need triggers, roll-ups, formulas, or offline access? Copy the data in.
- Do you need both a live single-row view and analytics? Build both, and don’t apologise for it.
The mistake I see most is answering question three with external objects because someone already had a Salesforce Connect adapter running. The adapter is not the decision. What the data is for is the decision.
Understanding the basics
Is Salesforce Connect the same as Data 360 zero copy?
No. Salesforce Connect exposes external tables as external objects for live, row-level use inside the CRM, through OData or a custom adapter. Data 360 zero copy federates queries against a data warehouse for analytics, segmentation, and AI grounding. They share the idea of not copying data and little else.
Can you report on external objects?
Partly. External objects support standard reports, but not if the external data source has High Data Volume turned on, and not with aggregate functions like SUM or GROUP BY. For real reporting across large external datasets, use Data 360 rather than Salesforce Connect.
Does zero copy work with any database?
No. Data 360 query federation supports Snowflake, Google BigQuery, Amazon Redshift, and Databricks. Other sources need a different path, either an OData external object through Salesforce Connect or ingestion into Data 360 as a data stream.
Do external objects count against my custom object limit?
No. You can create up to 200 external objects per org, and they are counted separately from custom objects.
Where to start
Write down which of the five questions above your use case answers, before anyone opens Setup. Most of the failures I get called into are a Salesforce Connect adapter doing an analytics job, or a zero-copy federation being asked to render a live row on a page. The tool was fine. It was pointed at the wrong problem.
If you are weighing external objects against Data 360 zero copy for a specific source, or an agent is timing out on external data, talk to us. We do this decision, and the integration work under it, for a living.