Data 360
The Data 360 credit circuit breaker: the kill-switch Digital Wallet won't give you
Digital Wallet will email you at 90% of your credit threshold. It will not stop the runaway job that's burning them. Here's how to build the missing half: a Flow-plus-Apex breaker that reads live consumption and clears the schedule on the offending workload before it bills, and the four gotchas that make an automated pause trickier than it looks.
Data 360’s consumption meter has one alarming property: nothing about a runaway job looks like an emergency until the invoice does. An identity-resolution ruleset re-evaluating profiles all day, a calculated insight someone set to refresh hourly when the decision it feeds changes once a night, a build team iterating against full production volume: each one draws credits and continuously, and the platform’s own monitoring will happily watch it happen. Digital Wallet fires a threshold alert at 90%, an email lands, and then… the job keeps running. Because the one thing Salesforce’s native consumption tooling does not do is stop consumption. It tells you the house is on fire. It does not turn off the gas.
That gap is the whole subject of this post. Salesforce ships the alerting half of a credit governor and leaves the acting half to you, and at TDX 2026 the platform team said as much, presenting circuit-breaker patterns that pair Flow with the Data 360 Connect API to pause a workload automatically when consumption crosses a line. This is the build. First why the native tooling stops where it does, then the three pieces of an actual breaker (read consumption, decide, pause) with the Apex and Flow to wire them, and finally the four gotchas that make “just pause it” less clean than it sounds. (One naming note up front: the product rebranded from Data Cloud to Data 360 in October 2025, but the APIs, DLO names, and much of the documentation still say data-cloud and c360, so you’ll see both throughout, and they mean the same platform.)
What Digital Wallet does, and the wall it hits
Give Digital Wallet its due first, because the breaker is built on top of it, not instead of it. It’s the native consumption surface for Data 360 and Agentforce, and it’s good at visibility:
- Consumption cards per product and resource, each viewable over a 24-hour, 7-day, 30-day, or 90-day window, so you can see which resource is driving spend.
- Consumption Insights, which drills into usage by type and day, and, usefully, is itself built on Data 360, storing its consumption records as data lake objects you can query.
- Usage Tagging, so a spike has a name (an environment, an agent, a feature) instead of being an anonymous number. This is the same discipline we push in the Flex Credit optimization playbook: you can’t govern what you can’t attribute.
- Consumption Threshold Alerts, delivered as a ready-to-use Flow you’ll find under Setup → Flows. Set a percentage limit, globally or per card, and it notifies in-app and by email, optionally to Slack, commonly staged at 25%, 50%, 75%, and 90%.
Read that list again and notice what every item has in common: they all observe. The threshold-alert Flow is the closest thing to control, and it still only sends a message. There is no out-of-the-box action that says “and now pause the data stream.” That’s not an oversight so much as a deliberately conservative default. Salesforce is not going to auto-halt your production data pipeline on a percentage rule and risk breaking your activations. But it means the closed loop, the part where detection does something, is yours to build. The good news: Salesforce also ships the primitives you need to build it, and the threshold-alert Flow is the perfect trigger to hang it on.
Digital Wallet is a smoke detector. A circuit breaker is the sprinkler. Salesforce sells you the detector as standard and hands you the parts for the sprinkler, the wiring is the project.
The anatomy of a breaker: read, decide, pause
A credit circuit breaker is three moving parts, and each maps to a primitive the platform exposes.
┌─────────────────────────────────────────────────────────┐
│ 1. READ Query TenantEnrichedUsageEvent (free) │
│ → credits consumed so far this period │
└───────────────────────────┬─────────────────────────────┘
│
┌───────────────────────────▼─────────────────────────────┐
│ 2. DECIDE Threshold-Alert Flow (or scheduled Flow) │
│ → is a card/usage-type over its limit? │
└───────────────────────────┬─────────────────────────────┘
│ invocable Apex
┌───────────────────────────▼─────────────────────────────┐
│ 3. PAUSE Connect API: PATCH /ssot/data-streams/{id} │
│ → clear the schedule → job stops running │
└─────────────────────────────────────────────────────────┘
Nothing here is exotic. It’s a query, a decision, and an authenticated callout, the same shape as any Flow-orchestrated HTTP integration you’d build for an external system, except the endpoint is Data 360’s own management API. Take the parts in order.
1. Read consumption without paying to read it
The breaker needs to know how many credits it has burned this period, and it needs to check often, which creates an obvious trap: querying Data 360 usually costs query credits, so a chatty monitor could add to the very bill it’s trying to cap. The escape is a specific object. Salesforce built and optimized TenantEnrichedUsageEvent, the data lake object behind Digital Wallet’s own reporting, so that you can query it without incurring query credits. It carries the units consumed, the resource that consumed them, the usage type, and the card name, everything a decision needs.
Add it to a data space, then read it the same way you’d read any Data 360 object from Apex, through ConnectApi.CdpQuery or the Query API:
public with sharing class CreditMonitor {
// Sum credits consumed this billing period for a given consumption card.
public static Decimal creditsUsedForCard(String cardName) {
String soql =
'SELECT SUM(UnitsConsumed__c) total ' +
'FROM TenantEnrichedUsageEvent__dll ' +
'WHERE CardName__c = \'' + String.escapeSingleQuotes(cardName) + '\' ' +
'AND EventTimestamp__c = THIS_MONTH';
ConnectApi.CdpQueryInput input = new ConnectApi.CdpQueryInput();
input.sql = soql;
ConnectApi.CdpQueryOutputV2 res = ConnectApi.CdpQuery.queryANSISqlV2(input);
// Parse the first row's aggregate; shape depends on your field API names.
return CreditMonitorParser.firstNumber(res);
}
}
Treat the exact DLO and field API names as something to confirm in your own org: the __dll/__cll suffixes and field names vary by how the object landed in your data space, and TenantEnrichedUsageEvent is the one name I’d verify against Setup before shipping. The principle is the load-bearing part: read from the free usage object, not from a query that meters.
2. Decide, and reuse the alert Flow you already have
You do not need to invent the detection layer. The Consumption Threshold Alerts Flow already fires at the percentages you configure; the move is to extend it. Where it currently ends in a notification, add a decision element and an Apex action: if the breached card matches a name on your “safe to auto-pause” list and the breach is at your hard ceiling (say 95%, above the 90% you merely warn at), call the pause action. Keep two thresholds deliberately apart (a lower one that only tells a human, and a higher one that acts) so the breaker is a backstop for the runaway you didn’t catch, not a hair-trigger on healthy load.
If you’d rather not couple to the alert Flow, a scheduled Flow that runs CreditMonitor every 15–30 minutes and branches on the number works identically. Either way, the decision is trivial arithmetic. All the engineering risk is in the third part.
3. Pause: clear the schedule through the Connect API
Here’s the mechanism that stops the burn, and it’s cleaner than you’d expect: you don’t “kill” a job, you clear its schedule. A scheduled data stream, calculated insight, or identity-resolution run consumes credits because it keeps running on a cadence. Set that cadence to nothing and it stops drawing. The Data 360 Connect REST API exposes this directly.PATCH /ssot/data-streams/{recordIdOrDeveloperName} updates a data stream, schedule included. Called from an invocable Apex method so a Flow can reach it:
public with sharing class CreditBreaker {
public class PauseRequest {
@InvocableVariable(required=true) public String dataStreamName;
}
@InvocableMethod(label='Pause Data 360 Data Stream'
description='Clears a data stream schedule to halt credit draw.')
public static void pause(List<PauseRequest> reqs) {
for (PauseRequest r : reqs) {
HttpRequest req = new HttpRequest();
// Named credential pointing at your org's Data 360 Connect API base.
req.setEndpoint('callout:Data360_ConnectAPI/ssot/data-streams/'
+ EncodingUtil.urlEncode(r.dataStreamName, 'UTF-8'));
req.setMethod('PATCH');
req.setHeader('Content-Type', 'application/json');
// Body: set the refresh schedule to none. Confirm the exact
// schedule object against the current Connect API spec for your
// version before relying on this in production.
req.setBody('{ "refreshFrequency": "None" }');
HttpResponse res = new Http().send(req);
if (res.getStatusCode() >= 300) {
throw new CalloutException('Pause failed for '
+ r.dataStreamName + ': ' + res.getStatus() + ' ' + res.getBody());
}
}
}
}
Two honest caveats baked into that code. First, the endpoint (PATCH /ssot/data-streams/{id}) is real and documented, but the exact request body for “no schedule” is a detail to confirm against the live Connect API spec for your API version. Don’t ship the body above without checking it. Second, to stop a list of workloads (every calculated insight of a given type, say) you loop this call over their identifiers, which is exactly what the TDX pattern demonstrated: Apex iterating the Connect API to pause a category of process, not just one stream. The same API surface reaches calculated insights, identity-resolution rulesets, and segments; data streams are just the clearest example.
The four gotchas that make this harder than “pause it”
A breaker that clears a schedule is easy to write and easy to get subtly wrong. Four realities separate a safe one from a footgun.
1. It can’t stop queries, only schedules. Pausing halts scheduled processing: streams, calculated insights, identity resolution, scheduled transforms and activations. It does nothing about live query consumption, an ad-hoc SQL storm or an agent hammering the Query API keeps billing right through your breaker. So a circuit breaker caps your scheduled burn, which is where the quiet overruns live, but it is not a total spend cap. If query volume is your problem, that’s a different governor. Closer to governing what an agent is allowed to retrieve than to pausing a pipeline.
2. Pausing makes data go stale. Silently. The instant you clear a stream’s schedule, everything downstream freezes at its last good state: unified profiles stop updating, segments compute against yesterday, activations into Marketing, Commerce, or CRM keep firing on data that no longer moves. Nothing errors. A segment that “looks correct on paper” simply activates on stale membership. That’s the real cost of the breaker, and it’s why the auto-pause list should contain workloads where stale-but-cheap beats fresh-but-runaway, a nightly enrichment, not the real-time signal an agent grounds on. Freshness is a chain, and pausing one link stops the whole thing quietly; if you haven’t already, wire up end-to-end freshness monitoring so a paused stream shows up as staleness you can see rather than a number that’s mysteriously old.
3. Re-enabling is stateful, capture the schedule before you clear it. Setting a schedule to “none” discards it. There is no “resume” that remembers the cadence you had; restoring means re-applying the original schedule, which means your breaker has to store the prior schedule before it pauses, or a human has to reconstruct it from memory at 2 a.m. Build the read-and-stash into the pause action: capture the current refreshFrequency (and its parameters) into a custom object keyed by stream, then clear it, so a companion “restore” Flow can put it back exactly. A breaker that pauses but can’t cleanly un-pause is a bigger operational risk than the overrun it prevents.
4. It stops future draw, not past draw. Credits meter as data is processed and sum cumulatively over the billing period. Tripping the breaker prevents the next scheduled run from consuming. It does not refund what the runaway already burned before the near-real-time signal caught it. And that signal is near-real-time, not instant, so a fast runaway can spend meaningfully in the minutes between crossing the line and the pause landing. The breaker is damage control on incremental spend, not a time machine. Which is the honest framing for the whole pattern: it’s the last line of defense, not the first.
Where the breaker sits in a real governance stack
An automated pause is the floor of a strategy, not the strategy. It catches the failure you didn’t prevent; most of the savings come from not creating the runaway in the first place. In rough order of use:
- Design for consumption, not storage. The single biggest lever is upstream of any breaker: don’t default to streaming when batch delivers the same business outcome. A streaming calculated insight costs on the order of 53× a batch one: the rate card puts streaming calculated insights around 800 credits per million rows against roughly 15 for batch, and 800 ÷ 15 is where that “53×” comes from. Reserve streaming for decisions that need sub-15-minute latency (a practitioner rule of thumb, not an official threshold) and batch everything else. This and the rest of the credit-optimization levers prevent far more spend than a breaker ever recovers, and the calculated-vs-streaming insight choice is the one that moves the meter most.
- Match every cadence to the decision it feeds. A calculated insight refreshing hourly to feed a report someone reads at 9 a.m. is 23 wasted runs a day. Salesforce’s own “credit feedback loop” guidance is blunt about it: most overruns come from processes nobody was watching, running more often than anything downstream needs.
- Scope build teams to a data-space slice. Iterating on full production volume is a classic silent overrun. Filter the objects feeding unification down to a representative sample during build, and native-source ingestion (Sales, Service, Marketing, Commerce Cloud) stays free regardless.
- Attribute with Usage Tagging, alert at staged thresholds, and, only then, auto-pause the safe list. Tags make spikes legible, alerts give a human the chance to intervene, and the breaker is the backstop for the case where no human was looking. That layering is the same posture that keeps an agent fleet from becoming shadow IT: visibility, ownership, and a hard stop of last resort.
What to build
Start with attribution, because a breaker you can’t target is dangerous. Turn on Usage Tagging, get every stream, insight, and segment named, and watch Digital Wallet for a fortnight to learn your own baseline. Turn on the Consumption Threshold Alerts Flow at 50/75/90 so a human sees trouble coming. Then build the breaker: a read action against TenantEnrichedUsageEvent (free), a decision at a ceiling above your warn line, and an invocable pause that captures-then-clears the schedule via PATCH /ssot/data-streams/{id}. Restricted to an explicit allow-list of workloads where staleness is survivable. Write the companion restore Flow before you write the pause, and test the whole loop in a sandbox against a deliberately over-scheduled insight so you watch it trip and recover once before it ever guards production.
Done that way, the breaker changes what a bad month feels like. Instead of discovering a five-figure overrun on an invoice, a runaway trips a scheduled pause, a stale-data alert, and a Slack message, a contained incident with a name attached, not a surprise with your signature on it. Salesforce gave you the smoke detector. This is the sprinkler it deliberately left for you to plumb.
Understanding the basics
Can Salesforce Data 360 automatically stop credit consumption?
Not out of the box. Digital Wallet monitors consumption and its Consumption Threshold Alerts Flow notifies you (in-app, email, optionally Slack) when usage crosses a percentage limit, but it has no native action that halts a workload. To pause consumption you build a “circuit breaker”: a Flow that reads current usage and, past a hard ceiling, calls invocable Apex that clears the schedule on the offending data stream, calculated insight, or identity-resolution run through the Data 360 Connect API. Salesforce ships the alerting and the API primitives; the closed loop is a DIY pattern, one the platform team demonstrated at TDX 2026.
How do you pause a Data 360 data stream programmatically?
You clear its schedule rather than “killing” it. The Data 360 Connect REST API exposes PATCH /ssot/data-streams/{recordIdOrDeveloperName}, which updates a data stream including its refresh schedule; setting the schedule to none stops it running and therefore stops it drawing credits. Call it from an invocable Apex method (via a named credential) so a Flow can trigger it, and loop the call over multiple identifiers to pause a whole category, every calculated insight of a type, say. Capture the existing schedule before you clear it, because there’s no automatic resume that remembers the old cadence.
How can I check Data 360 credit usage without spending credits to check it?
Query TenantEnrichedUsageEvent, the data lake object that powers Digital Wallet’s own reporting, which Salesforce optimized so you can read it without incurring query credits. It carries units consumed, the resource and usage type responsible, and the consumption card name, which is enough to drive both dashboards and an automated breaker. Most other usage DLOs do cost query credits when queried, so route any frequent, automated monitoring through TenantEnrichedUsageEvent specifically to avoid a monitor that inflates the bill it’s meant to protect.
What are the risks of automatically pausing Data 360 workloads?
Four. It only stops scheduled processing, not live queries, so it isn’t a total spend cap. It makes everything downstream go stale silently: profiles, segments, and activations keep serving frozen data with no error. Re-enabling is stateful: clearing a schedule discards it, so you must store the prior schedule to restore it cleanly. And it only prevents future draw. Credits already consumed before the near-real-time signal fired aren’t refunded. Together these mean a breaker belongs on an allow-list of workloads where stale-but-cheap beats fresh-but-runaway, with a tested restore path, as a last line of defense behind good cadence and batch-vs-streaming design.
Staring at a Data 360 bill that outran its forecast, or want the governance (tagging, alerts, and a tested breaker) built before the next surprise? Talk to us. Getting the data foundation both trustworthy and affordable, so it can ground an agent without bankrupting the project, is exactly the work we do.