CHAMPS · Chalky

Find the pricing faults that never raise an error. 21 checks. Your revenue estate.

Revenue Cloud Advanced fails quietly. An empty decision table returns blanks rather than an error, a stale one answers from whenever it was last refreshed, and an attribute value that matches no adjustment simply does not fire. Everything reads as though it worked, and the first person to find out otherwise is the customer holding the invoice. Chalky reads your pricing procedures, decision tables, product catalog and constraint model against twenty-one published checks.

How it goes wrong

An empty decision table returns blanks, not an error

None of the four below is a bug. Each is the platform doing exactly what it was configured to do, which is why nothing in the org raises a hand.

The table answers from its last refresh

A decision table is a compiled snapshot, not a live query. Change the price book on Friday and the table keeps returning what it held on Tuesday until something refreshes it — and nothing refreshes it on its own. The cheap fix has a ceiling too: an incremental refresh has to be preceded by a full one, and above two thousand changed records it fails outright and a full refresh is the only way back.

Salesforce Help: Refresh a Decision Table

Cloning a context definition opts it out of the upgrades

Extending the standard definition is the path that keeps receiving: it carries automatic upgrades and a Sync Now option, so the mappings each release adds arrive on their own. Cloning looks equivalent and is not — Salesforce’s own comparison gives a cloned standard definition “no automatic upgrades”. The exception is worth knowing, because it is exactly what a scan has to look for: a clone of an already-extended definition keeps its upgrades only if Preserve Inheritance was ticked when it was made.

Worse than either is a definition carrying both lineages at once, which a separate Salesforce article (KB 004259656) says “can result in unexpected pricing errors and should be recreated”. Recreation is the honest word: an active definition cannot be edited, and it will not deactivate while anything still references it.

Salesforce Help: clone versus extend

Only the last conditional default reliably evaluates

Where two setdefault rules in a constraint model target the same assignment, the best-practices guide is blunt: “Only the last rule will reliably evaluate.” The earlier ones are not lower priority, they are unreliable. And because a setdefault fires only when its condition changes, the order dependence stays invisible to a test that passes.

Salesforce: CML best practices

A procedure stops at 130 elements, and the queue is a support case

A pricing procedure version gets a hundred and thirty pricing elements by default, and the wall announces itself the moment somebody saves the change that crosses it. Raising it is not self-service: it is a case with Salesforce’s Revenue Cloud feature activation team, assessed individually for performance impact, and the documented ceiling is two hundred. Knowing you are at ninety-nine is a planning conversation. Discovering it at a hundred and thirty is a stopped release.

Salesforce Knowledge 005385232
What it finds

One real org: three prices written into the procedure that quotes every deal

On one real Revenue Cloud Advanced org, twenty-one checks ran and ten of them failed. The active pricing procedure carried three hardcoded prices, and a set of discount thresholds written straight into a filter alongside them. None of it is visible to anyone who manages pricing through the catalog, and changing any of it needs a builder editing and re-activating a procedure version rather than somebody updating a row.

That same procedure sat at ninety-nine elements of the hundred and thirty a version gets by default. Five decision tables were referenced by live pricing elements and held no rows at all. Of 2,356 active products, 1,311 carried no description; all 1,204 component rows carried no minimum, no maximum and no required flag, so nothing bounded the configurator anywhere; and 142 products sat in 41 near-duplicate name clusters, where a contract term, a version number or in one case a rate had been written into the product name.

None of it was throwing an error. The org was quoting.

The checks · Pricing procedures

Prices written into procedure logic, where the people who manage pricing cannot see them

Five checks on the procedures themselves: what the engine actually does when a quote arrives, and whether the catalog would tell you.

Hardcoded constants in pricing expressions

RC-001 · Medium

A rate, a price or an uplift sitting inside a pricing element formula or parameter instead of a decision table or price book reference. Finance reads one price in the catalog while the engine charges another, and the copies drift apart silently because nothing in data governance can see them.

Salesforce Help: pricing elements

Condition ladder where a decision table belongs

RC-002 · Medium

A chain of conditional cases — per-segment rates, per-tier discounts — doing the job of one indexed lookup. Every new tier becomes a version edit and a re-activation instead of a row, and every step spends the procedure’s one-minute runtime budget and one of its hundred and thirty elements.

Kavaliro: pricing procedures

Ad hoc custom fields mapped into the pricing context

RC-003 · Low

Context mappings pulling loosely named custom fields where a standard pricing attribute exists. The context definition is the contract between quote data and the engine: couple it to unstable schema and a rename surfaces as a pricing fault at quote time, in front of a seller.

Salesforce Knowledge 004259656

Manual arithmetic standing in for aggregation elements

RC-005 · Medium

Assignment arithmetic re-deriving group totals that the aggregation element computes once. Hand-rolled copies diverge the moment one is edited, and the price waterfall stops explaining itself — which is the debuggability the platform is sold on. Two documented gaps are carved out, not flagged: derived products, and rollup to quote or order headers.

Salesforce Help: pricing elements

Pricing procedure near the element ceiling

RC-011 · Medium

How close each active procedure version is to the hundred-and-thirty-element default. It is raisable by a support case up to a documented maximum of two hundred, assessed individually for performance impact — so the number worth knowing is the one before you hit it, not after.

Salesforce Knowledge 005385232
The checks · Decision tables and versions

A table that answers from whenever it was last refreshed, and nothing says when that was

Three checks on the snapshots your pricing actually reads, and on the versions sitting around the ones in use.

Stale decision table

RC-008 · High

Source rows modified after the table last synced. The quote is wrong and the engine is not: it answered correctly from the snapshot it holds. The gap shows up as a margin surprise weeks later, or as a customer comparing their quote with their invoice.

Salesforce Help: Refresh a Decision Table

Decision table compiled from an empty dataset

RC-020 · High

An active table holding no rows while a live pricing element still calls it. No match is a designed, silent outcome, so the failure arrives as a blank rather than an error — and it cuts both ways: an unapplied contracted discount reaches the customer as an overcharge, not as a margin report.

Salesforce Help: Refresh a Decision Table

Expression set version sprawl

RC-004 · Low

Inactive versions piling up, and undated drafts sitting ahead of the active one. Deploying a procedure creates a new version by default, so sprawl is what normal delivery produces rather than what carelessness produces. The cost is somebody debugging version 25 while version 24 prices the quotes — or activating 25 believing it is a small step. A draft with a future start date is deliberate staging and is not flagged.

Salesforce Help: pricing procedures
The checks · Product catalog

A catalog that grew a product every time a price did

Four checks on the catalog everything else reads from — quoting, pricing, billing and renewals all take it as given.

SKU proliferation standing in for attributes

RC-012 · Advisory

Near-duplicate products differing only by a token an attribute should carry: a size, a term, a tier. Attributes exist so one product covers the variations; where they are not used, the catalog multiplies, and every downstream process inherits the multiplication. Reported as advisory because some splits are deliberate — distinct fulfilment or revenue treatment is a real reason to keep two records.

Cloud Giants: Revenue Cloud products

Cardinality unbounded in model and master data

RC-015 · Medium

Component relations carrying no minimum, maximum or required flag in the constraint model and none in the catalog either. Bounds are not tidiness — they are what the solver searches within, and they are what stops a seller removing a bundled component or ordering a quantity the business never agreed to. Flagged only when both places are empty; either one alone is a bound.

Salesforce: CML best practices

Free-text attribute driving pricing

RC-009 · Medium

A price-impacting attribute typed as text with no picklist behind it. Attribute matching is exact and has no wildcard, and a value that matches nothing does not raise anything — the adjustment simply does not fire. “CA”, “California” and “CALIF” are three prices. This check is drawn from practitioner sources rather than an official page; we have not found one that states it, and say so rather than linking something that nearly does.

Catalog hygiene floor

RC-013 · Low

Active products with no description, or names that follow no convention. A product name is the only interface most approvers ever get: a deal desk that cannot see what it is approving approves it anyway, and the catalog sits at the core of quoting, pricing, billing and renewals alike.

Cloud Giants: Revenue Cloud products
The checks · Context definitions and routing

Cloned instead of extended, and frozen at the release it was cloned in

One disease with four symptoms. Salesforce names cloning as the cause in three separate knowledge articles, and the check it prescribes is a human reading a field on every definition, one at a time.

Context definition with both ClonedFrom and InheritedFrom

RC-006 · High

Two contradictory lineages on one definition. The sanctioned remedy is to recreate it, not to repair it — and recreation means repointing every procedure and rule that references it, because an active definition cannot be edited and will not deactivate while anything still points at it.

Salesforce Knowledge 004259656

Cloned context definition missing standard mappings

RC-007 · High

A definition created by cloning rather than extending, with no inheritance preserved, so the mappings later releases added to the standard one never reached it. It fails at the point of sale, mid-deal. The check keys on Inherited From being empty where Cloned From is not — which is both the documented resolution step for the error and the precise line between a clone that still receives upgrades and one that does not.

Salesforce Knowledge 004259656

No default pricing procedure fallback

RC-010 · High

A quote matching no routing rule and finding no default behind it. We check that a default is set and that its context definition genuinely inherits from the standard one, because a default backed by a clone fails in exactly the same way as no default at all.

Salesforce Knowledge 002183049

Discovery and pricing procedures on different context definitions

RC-019 · High

The two halves of the pricing path pointing at different definitions. The prescribed check is to open both and compare what they display, which is precisely the check that has been reported failing — both screens agreeing while the error persisted. We compare the stored associations instead of what the page renders.

Salesforce Knowledge 002188066
The checks · Constraint model

A configurator that accepts what it was built to refuse

Five checks on the constraint model itself — the language that decides what can be configured together, and how long the solver takes to decide it.

Pricing fields inside a constraint model

RC-014 · High

List price, net unit price and their relatives referenced in model source. The developer guide is explicit: pricing fields “are not supported in CML and should not be used in constraint models”. Not supported, which is a different promise from raising an error when you use them anyway.

Salesforce: CML best practices

Quantity fields driving component creation

RC-016 · High

Line item quantity used to create components rather than read them. The engine validates such an expression but does not configure to satisfy it, and every extra value in a quantity domain is another combination for the solver to test. Cardinality is the mechanism designed for the job; quantity is the one that grows the search space.

Salesforce: CML best practices

Conflicting setdefault rules on one target

RC-017 · Medium

More than one conditional default aimed at the same assignment. The documented fix is to collapse the conditions into a single derived variable and set the default once from it — which is also the only way to know which value a configuration will actually start with.

Salesforce: CML best practices

Relations declared against constraint order

RC-018 · Low

Relation declarations not following the documented left-hand-side-first ordering. The lightest check in the set, and reported as such: Salesforce’s guide says the order matters for constraint evaluation, and nobody outside Salesforce has published a measurement of what it costs.

Salesforce: CML best practices

Constraint model out of sync with product definitions

RC-021 · Medium

A model that has not been synced since the product definitions underneath it changed. Salesforce ships the sync so that, in its own words, “the CML reflects the latest product definition” — which is also an admission that it does not on its own. Until somebody runs it, the configurator is checking against an older shape of the product than the catalog holds.

Salesforce Help: rules and constraints
What you get

Every failed check answers what it costs the business, and what to do about it

Cloud HikersChalky
Client
Sample Ltd
Evaluated org
sample--uat.sandbox.my.salesforce.com
8failed
of 21
Chalky · Revenue Cloud Advanced audit6 procedures · 31 decision tables · RCA rules v1.0.1 · 21 checks
What the scan found

8 failed checks across the revenue estate

Twenty-one checks were run against this org’s pricing procedures, decision tables, product catalog and constraint model. 8 of them failed. 3 high severity failures sit in the group that prices quotes wrongly without raising anything: a decision table answering from a stale refresh, a table referenced by a live pricing element and holding no rows, and a context definition cloned rather than extended. Four medium and one low severity finding affect how safely pricing can be changed later.

Every check applied to this org. Where one cannot — no constraint model, no decision tables — it is reported as not applicable, never counted as a pass.

3 high severity4 medium severity1 low severity
Where the failures sit
Pricing procedures2 of 5 failed
Decision tables and versions2 of 3 failed
Product catalog2 of 4 failed
Context definitions and routing1 of 4 failed
Constraint model1 of 5 failed
Worst first
RC-008

Stale decision table

HighPricing integrity
Found in this org

Tiered_Discount_Entries last synced 14 May. Its source object Discount_Tier__c was modified 62 days later, on 15 July.

What this means for the business

The engine is not wrong: it is answering correctly from the snapshot it holds, which is two months old. Quotes carrying these tiers use May’s discounts. Nothing errors, so the gap surfaces either as a margin surprise weeks later or as a customer comparing their quote against their invoice.

Recommendation

Refresh the table, then make the refresh automatic rather than remembered: the invocable refresh action behind a record-triggered flow on the source object, with a debounce so a bulk edit queues one refresh and not a hundred. Give it an owner. The same discipline is what makes the fix for RC-002 safe — a condition ladder converted to a decision table is only an improvement if something keeps the table current.

A sample, not a client’s. Every count, name and date in it is invented, and deliberately not the result of any scan we have run. The structure, the rule and the source are the real ones.

Evidence from your own org

The procedure, the element, the literal value we read. Not that a rule exists — the string itself, so your architect can open the same record and see what we saw.

What it means for the business

What breaks, who finds out and when, written from the mechanism. Never a revenue figure: there is no honest way to price a finding from a sandbox, and inventing one would discredit the twenty beside it.

A recommendation, cross-linked

What to do, and where one piece of work closes two findings. Folding a condition ladder into a decision table also buys back procedure headroom, so the report says so rather than billing it as two jobs.

Checks that did not apply, named

A check that cannot apply to your org — no constraint model, no decision tables — is reported as not applicable. That is org truth, and it is not a pass.

What it costs

From £995, capped at £1,950, and the price falls as the catalog gets smaller

Priced from the size of the estate the report has to read — never per seat and never per user. Charities pay half, applied automatically at the quote. The scan itself is free: connect a sandbox and the preview comes by email, naming every check that failed. The report is the part you pay for, and only once you have seen what is in it.

The report is priced from the size of the estate it has to read, and two numbers describe that. Both are counted from your own org at the quote — these are here so you can see the shape of the price before you talk to anybody.

300 products and 240 pricing elements is 300 units — the larger of the two measures, counting one unit per two pricing elements, so a thin catalog driven by a large procedure estate is not priced as a small job.

The RCA report
£1,950+ VAT, once
Entry
£300
300 units at £10 / £8 / £6 / £4
£1,950
Capped at £1,950
£300

The cap is doing the work here. Past 234 units every org pays the same £1,950, so how much has accumulated in the catalog stops changing the bill.

Next time, once it is tidier
£1,810the following scan

Act on the catalog findings, take 30% of the products out, and the same report on the same org costs £140 less. We are paid for the mess only until it is cleared.

Change how much of the catalog is duplication

210 products left, which is 210 units.

The flow report is on the self-serve checkout today. The RCA report is priced, and all twenty-one checks above are built and running, but it is not on the checkout yet — ask us and we will run it. Buying both puts 20% off the flow charges; the RCA report itself is never discounted.

Indicative. The price you pay is counted from your own org, not from the numbers you typed here, and it is shown before anything is charged. All prices exclude VAT. Orgs running the Nonprofit Success Pack or Nonprofit Cloud pay half. 1% of every purchase goes to removing CO₂ from the atmosphere, through Stripe Climate.

How it works

One connection and one scan of the org; the two reports are what differ

1 · Connect

A minimal integration user in your sandbox, one login with Salesforce’s own CLI, and a connection URL pasted into the connect page. About ten minutes, and it is the same connection the flow scan uses.

2 · Read

The catalog and component census in bulk, every active pricing procedure and constraint model retrieved in full, then all twenty-one checks evaluated. The org in the band above — 2,356 products, four procedures — took minutes, not days.

3 · Report

One report at org level rather than one per product: the checks that failed, worst first, each with the evidence, the consequence and the recommendation, and the checks that passed listed so you can see what was looked at.

4 · Fix, and pay less next time

Act on the catalog findings and the estate is smaller when it is next read — and the next quote is priced from what is there then, not from what was there before.

Frequently Asked Questions

Will it touch the org?

No. Chalky reads metadata and configuration and changes nothing, and it points at a sandbox — there is no production option to choose. What the connection can reach is bounded by the user you connect it with, and removing that user’s access in your own Setup ends ours without asking us.

Is this the same thing as RLM?

Yes. Revenue Lifecycle Management was renamed: Revenue Cloud Advanced, or Agentforce Revenue Management where it is sold with the agent layer. Salesforce knowledge articles and error strings still carry the old name in places, and the report quotes them exactly as they are written.

We are still on CPQ. Is there anything here for us?

Not yet for the procedure and constraint checks — they read Revenue Cloud Advanced objects a CPQ org does not have. The catalog is the part that carries over, and duplicate products, inconsistent naming and legacy bundles carry over with it. Rationalising before the migration is cheaper than discovering it after.

How many of the twenty-one actually run?

All twenty-one. A check we have not built never appears in a report at all, and a check that cannot apply to your org is reported as not applicable rather than counted as a pass. The last org run against this ruleset returned ten failures, eleven passes and nothing unevaluated.

Twenty-one checks against every pricing procedure, decision table and product in your org

One read-only connection to a sandbox, and the same connection that reads your flows reads your revenue estate. The scan costs nothing and the preview names every check that failed; the report is what you pay for.

Scan my revenue estate