Pricing, Ramp Deals & Discounting
A deep-dive comparison for Salesforce architects and senior consultants covering how Salesforce CPQ (SteelBrick origin) and Salesforce Revenue Cloud each handle volume pricing tiers, negotiated discounts, multi-year ramp schedules, and the automation engines that power them.
Use Case, User Journey & Personas
Who uses pricing & discounting capabilities — and how they navigate the workflow
When to Use — CPQ Pricing
- ✓Volume / tier pricing: Discount Schedules with manual or automatic tier selection (volume, slab, or flat).
- ✓Ramp deals: MDQ (Multi-Dimensional Quoting) for year-over-year quantity or price escalations on subscription products.
- ✓Negotiated discounts: Rep-editable Discount fields with approval thresholds; Price Rules lock or override prices.
- ✓Block / stair-step pricing: Block pricing calculates price by ranges; most suitable for high-volume SaaS or manufacturing.
- ~Partner / channel pricing: Pricebook-per-partner works but lacks native deal registration; Partner Community extensions required.
- ~Cross-product bundle discounts: Achievable with Price Rules, but rule management becomes complex at scale.
When to Use — RC Pricing
- ✓Volume / tier pricing: PricingTier objects with PricingPlan rules handle graduated, volume, and flat-rate models natively.
- ✓Ramp deals: First-class RampInterval objects; each interval can carry independent quantity, discount, and price overrides.
- ✓Negotiated discounts: PriceAdjustmentSchedule supports manual, rule-based, and API-driven adjustments with full audit trail.
- ✓Dynamic / attribute-driven pricing: Pricing Variables allow price to be calculated based on attributes (seats, bandwidth, usage).
- ✓Partner / channel pricing: Account- and segment-scoped Pricing Plans enable true multi-tier partner pricing without custom code.
- ✓Usage-based and hybrid models: Pricing Procedures natively support metered + committed hybrid pricing in a single transaction.
Internal & External Personas
Sales Representative
Selects price book, applies manual discount within threshold, configures ramp quantities, submits for approval.
Deal Desk / Rev Ops
Reviews quotes above discount threshold, models alternative ramp structures, approves complex pricing scenarios.
Pricing Manager
Maintains discount schedules, defines pricing rules & procedures, sets approval thresholds per product line.
Finance / FP&A
Audits realized vs list pricing, reviews ramp deal TCV and ACV, validates revenue recognition schedules.
Partner / Reseller
Accesses partner-scoped pricebook or Pricing Plan via Experience Cloud; submits orders with tier-qualified pricing.
Salesforce Architect
Designs pricing data model, implements automation engine, governs customization and performance of price calc.
User Journey: CPQ
User Journey: Revenue Cloud
2.1 Summary — Architectural Guidance
- CPQ's pricing journeys are well-understood and heavily field-tested but become brittle with 50+ Price Rules; governance discipline is essential.
- Revenue Cloud's Pricing Procedures are more maintainable for complex logic but require architects familiar with Flow orchestration patterns.
- For partner pricing at scale, RC's account-scoped Pricing Plans eliminate the proliferation of custom pricebooks required in CPQ.
- Both platforms share the same Approval frameworks (Process Builder / Flow / Approval Process), so persona workflows converge post-price-calc.
Licensing Requirements
Which license tier unlocks each pricing capability
| Capability | CPQ Standard | CPQ+ | RC Base / Growth | RC Advanced / DX |
|---|---|---|---|---|
| Basic List Pricing | ✓ Included | ✓ Included | ✓ Included | ✓ Included |
| Discount Schedules (Volume, Slab) | ✓ Included | ✓ Included | ✓ via Pricing Tiers | ✓ via Pricing Tiers |
| Block Pricing | ✓ Included | ✓ Included | ✓ Pricing Tiers | ✓ Pricing Tiers |
| Price Rules (Basic) | ✓ Included | ✓ Included | ✓ Pricing Procedures (Flow) | ✓ Pricing Procedures (Flow) |
| MDQ (Multi-Dimensional Quoting) | ✗ CPQ+ only | ✓ Included | ~ Manual intervals | ✓ RampInterval object |
| Subscription Pricing Rules | ✓ Included | ✓ Included | ✓ Included | ✓ Included |
| Pricing Variables (Attribute-Driven) | ✗ QCP workaround | ~ QCP custom JS | ~ Limited to base attrs | ✓ Full PricingVariable |
| Pricing Procedures (Flow Orchestration) | ✗ Not available | ✗ Not available | ✓ Included | ✓ Included + extensions |
| Account/Segment-Scoped Pricing Plans | ✗ Pricebook workaround | ✗ Pricebook workaround | ~ Basic plan scoping | ✓ Full plan scoping |
| Ramp Interval Auto-Calculation | ✗ CPQ+ MDQ only | ✓ MDQ segments | ~ Manual interval | ✓ Auto-generate intervals |
| External Pricing Engine API Integration | ~ QCP callout | ✓ QCP callout | ~ Flow HTTP callout | ✓ Pricing Procedure + API |
| Quote Calculator Plugin (QCP) | ✓ Included | ✓ Included | ✗ N/A (Flow replaces) | ✗ N/A (Flow replaces) |
Licensing Gotchas
- MDQ is the single most common CPQ upgrade trigger — confirm CPQ+ licensing early when ramp deals are in scope.
- Revenue Cloud "Advanced" (formerly Revenue Cloud DX / Advanced Revenue Cloud) is required for full RampInterval and PricingVariable support; confirm SKU with AE before architecting solutions.
- QCP (JavaScript-based) requires CPQ+ for production callouts to external systems and is deprecated in RC — plan migration to Flow-based Pricing Procedures on any RC modernization project.
- Pricing Plan account/segment scoping is only available in Revenue Cloud Advanced; base RC restricts plans to pricebook-style global contexts.
2.2 Summary — Licensing Decision Points
- For greenfield: if ramp deals and attribute-driven pricing are required, target Revenue Cloud Advanced from the start.
- For CPQ existing: validate MDQ availability (CPQ+) and QCP usage before any migration planning.
- Hybrid scenarios (CPQ for new business, RC for renewals) require careful license mapping to avoid double-licensing gaps.
Data Model
Core objects, their purpose, and platform origin for pricing, ramp, and discounting
CPQ Objects
| Object API Name | Display Name | Purpose in Pricing | Type | Key Fields |
|---|---|---|---|---|
SBQQ__PricebookEntry__c |
Price Book Entry | Stores list price per product per pricebook; starting point of all CPQ price calculations | CPQ-Extended | UnitPrice, SBQQ__DefaultPricingMethod__c |
SBQQ__DiscountSchedule__c |
Discount Schedule | Defines a tiered discount structure (Volume, Slab, or Flat) associated with a product or product family | CPQ-Specific | SBQQ__Type__c, SBQQ__DiscountUnit__c, SBQQ__BundleComponent__c |
SBQQ__DiscountTier__c |
Discount Tier | Child of Discount Schedule; each record defines a range boundary and the discount % or amount for that tier | CPQ-Specific | SBQQ__LowerBound__c, SBQQ__Discount__c, SBQQ__Price__c |
SBQQ__QuoteLine__c |
Quote Line | Central pricing record; contains list, special, regular, customer, net, and partner price fields; waterfall anchor | CPQ-Specific | SBQQ__ListPrice__c, SBQQ__Discount__c, SBQQ__NetPrice__c, SBQQ__CustomerPrice__c, SBQQ__PartnerPrice__c |
SBQQ__SubscriptionPricing__c |
Subscription Pricing (field) | Field on Product2; controls how subscription price is calculated (Fixed, Percent of Total, Custom) | CPQ-Specific | SBQQ__SubscriptionPricing__c, SBQQ__SubscriptionPercent__c |
SBQQ__QuoteLineMDQ__c |
MDQ Quote Line Group | Container for each ramp segment (year) in an MDQ quote; holds segment-level quantity and pricing | CPQ+ Only | SBQQ__StartDate__c, SBQQ__EndDate__c, SBQQ__Quantity__c, SBQQ__SegmentLabel__c |
SBQQ__PriceRule__c |
Price Rule | Conditional logic to evaluate and modify quote/line fields; fires in pricing waterfall sequence | CPQ-Specific | SBQQ__Conditions__c, SBQQ__Actions__c, SBQQ__EvaluationEvent__c, SBQQ__EvaluationOrder__c |
SBQQ__PriceAction__c |
Price Action | Child of Price Rule; defines what field to set and the source (formula, field, or lookup) | CPQ-Specific | SBQQ__TargetField__c, SBQQ__ValueInput__c, SBQQ__PricingMethod__c |
Revenue Cloud Objects
| Object API Name | Display Name | Purpose in Pricing | Type | Key Fields |
|---|---|---|---|---|
PricingPlan |
Pricing Plan | Top-level container that groups pricing rules and tiers; can be scoped to account, segment, or channel | RC-Standard | Name, StartDate, EndDate, IsActive, PricingPlanType |
PricingVariable |
Pricing Variable | Named variable resolved at runtime from product attributes, quote fields, or external sources; feeds pricing procedures | RC-Standard | VariableName, DataType, Source, SourceField |
PricingTier |
Pricing Tier | Defines quantity or value ranges for volume/graduated/slab pricing under a Pricing Plan; replaces SBQQ DiscountTier | RC-Standard | LowerBound, UpperBound, AdjustmentType, AdjustmentValue |
PriceAdjustmentSchedule |
Price Adjustment Schedule | Stores a set of date-effective or quantity-effective price adjustments; the RC equivalent of CPQ Discount Schedules | RC-Standard | AdjustmentMethod, AdjustmentType, EffectiveStartDate, Status |
RampInterval |
Ramp Interval | Represents a single segment of a ramp deal (e.g., Year 1, Year 2); child of an Order or Quote product line | RC-Standard | StartDate, EndDate, Quantity, ListPrice, AdjustedPrice, Discount |
AdjustmentMethod |
Adjustment Method | Enumeration defining how a discount is applied: PercentOff, AmountOff, OverridePrice, or PercentOfTotal | RC-Enum | Picklist field referenced on PriceAdjustmentSchedule and PricingTier |
PricingProcedure |
Pricing Procedure | Named invocable Flow that orchestrates the full pricing calculation pipeline for a product or quote | RC-Standard | FlowApiName, ExecutionOrder, IsActive, TriggerEvent |
Pricebook2 |
Price Book | Standard Salesforce object; used by both CPQ and RC as the top-level currency/channel container for list prices | Platform-Standard | Name, IsActive, IsStandard, CurrencyIsoCode |
PricebookEntry |
Price Book Entry | Standard object linking Product2 to a Pricebook with a unit price; foundation of both CPQ and RC pricing | Platform-Standard | UnitPrice, UseStandardPrice, IsActive |
Revenue Cloud — Core Object Deep Dive
PricingProcedure
RC-Standard
FlowApiName— the underlying Flow invokedExecutionOrder— sequence within a pipelineIsActive,TriggerEventApplicableChannel— Sales / Partner / Self-Service
PriceAdjustmentSchedule
RC-Standard
SBQQ__DiscountSchedule__c. Defines a named set of adjustments (volume tiers, promotional, contractual) that can be applied to product lines at runtime. Supports both time-effective and quantity-effective structures.AdjustmentMethod— PercentOff / AmountOff / OverridePriceAdjustmentType— Volume / Slab / Flat / GraduatedEffectiveStartDate/EffectiveEndDateStatus— Draft / Active / Archived
PricingTier
RC-Standard
PriceAdjustmentSchedule. Each record defines one range band — lower/upper bound and the adjustment for that band. Direct replacement for SBQQ__DiscountTier__c with cleaner field names and no namespace prefix.LowerBound/UpperBoundAdjustmentValue— the discount % or amountAdjustmentType— inherited or overridden per tierPriceAdjustmentScheduleId— parent lookup
RampInterval
RC-Standard
StartDate/EndDateQuantity,ListPrice,AdjustedPriceDiscountQuoteLineItemIdorOrderItemId— parent
PricingVariable
RC-Standard
PricingProcedure steps without any JavaScript — no Quote Calculator Plugin equivalent needed.VariableName,DataTypeSource— ProductAttribute / QuoteField / Lookup / ExternalSourceField— API name of the resolved fieldDefaultValue
PricingPlan
RC-Standard
Name,PricingPlanTypeStartDate/EndDateIsActiveScope— Account / Segment / Channel / Global
How RC Pricing Objects Get Created
| Object | Creation Method | Who Creates It | Frequency | Notes |
|---|---|---|---|---|
PricingProcedure |
Revenue Management Settings UI + Flow Builder | Pricing Architect / Admin | Low (1–5 per pricing strategy) | Each procedure is a Flow; activate/deactivate like any Flow — no code deployment needed |
PricingVariable |
Setup → Pricing Variables tab | Pricing Architect / Admin | Low–Medium (library grows per product type) | Defined once, reused across procedures; source can be attribute, field, or external API |
PricingPlan |
Revenue Management app → Pricing Plans tab, or Data Loader | Pricing / RevOps Admin | Medium (per market segment or promotion) | Date-effective; future plans can be staged before go-live |
PriceAdjustmentSchedule |
Revenue Management app → Adjustment Schedules tab, or Data Loader | Pricing / RevOps Admin | Medium (per product family or discount program) | Replaces SBQQ__DiscountSchedule__c; bulk-load viable for large matrices |
PricingTier |
Adjustment Schedule detail page → Tiers tab, or Data Loader | Pricing Admin | Per schedule (many tiers) | No 12-tier limit; bulk-load recommended for volume discount matrices |
RampInterval |
Auto-generated by pricing engine when seller creates a ramp deal | System (via quote/order line) | Per ramp product line | Seller sets interval count and per-period quantities in the ramp editor UI; no admin coding per deal |
Pricebook2 / PricebookEntry |
Setup → Products → Pricebooks, or Data Loader | Pricing / RevOps Admin | Low (shared platform standard) | Used by both CPQ and RC as stable baseline; migration anchor for list price |
PricingProcedure, PricingVariable, PriceAdjustmentSchedule, and PricingTier records are pre-configured by pricing admins. Sellers interact with pricing only at runtime via the quote line editor or the Agentforce Quote Agent — which reads pricing output but does not write to pricing configuration objects. The only runtime-written pricing record is RampInterval, which is auto-generated when a seller creates a ramp deal in the quote UI.
Data Model Architecture Note
- CPQ extends standard
PricebookEntrywith custom fields viaSBQQ__namespace; Revenue Cloud instead introduces parallel platform-standard objects avoiding namespace pollution. - The MDQ pattern in CPQ creates child
SBQQ__QuoteLineMDQ__crecords; in RC theRampIntervalobject serves the same role but is directly queryable without namespace prefixes. PricingVariableis the key differentiator — it enables RC to perform attribute-driven pricing natively without JavaScript callbacks, significantly reducing maintenance burden.- Both systems ultimately resolve to standard
PricebookEntry.UnitPriceas the baseline, so migration scripts can use this as a stable anchor.
2.3 Summary — Data Model Comparison
- RC's data model is significantly cleaner — no namespace prefixes, purpose-built objects, and direct platform API queryability via SOQL and Connect APIs.
- CPQ's model is mature and battle-tested but tightly coupled to the SteelBrick namespace; integrations must account for
SBQQ__prefixes throughout. - For migration projects: map
SBQQ__DiscountSchedule__c→PriceAdjustmentSchedule,SBQQ__DiscountTier__c→PricingTier,SBQQ__QuoteLineMDQ__c→RampInterval.
Automations
Pricing engines, calculation pipelines, and automation mechanisms
CPQ Pricing Waterfall
Revenue Cloud Pricing Procedure Pipeline
Automation Capability Comparison
| Automation Capability | CPQ Mechanism | RC Mechanism | CPQ | RC | Notes |
|---|---|---|---|---|---|
| Conditional Price Overrides | Price Rules (conditions + actions) | Pricing Procedure Decision Elements (Flow) | ✓ | ✓ | RC Flow approach is more testable; CPQ rules can become hard to debug at scale |
| Lookup Table Pricing | Price Lookup Object + Price Rule | Custom SOQL in Flow / PricingVariable source | ✓ | ✓ | CPQ has native UI; RC requires custom Flow element or custom object |
| JavaScript Price Extensions | QCP — onCalculate, onBeforeCalculate, onAfterCalculate | Not applicable — replaced by Flow | ✓ | ✗ | QCP is a CPQ-specific concept; RC architects use Flow Apex actions instead |
| External Pricing API Callout | QCP async callout (with Named Credentials) | Pricing Procedure HTTP callout step via Flow | ✓ | ✓ | Both support external engines; RC Flow callout is more governed |
| Auto-Ramp Calculation | MDQ segments; no formula — manual input | RampInterval auto-generation with escalation formula | ~ | ✓ | RC can auto-generate intervals with % escalation per period; CPQ requires manual entry per segment |
| Dynamic Trigger Events | Evaluation events: Init, Save, Calc (limited) | Multiple triggers: add to cart, qty change, attr change, API | ~ | ✓ | RC pricing is event-driven and API-first; CPQ evaluation events are more rigid |
| Price Procedure Unit Testing | QCP unit tests in Jest | Flow unit tests via Apex Test or Flow Test (Summer '24+) | ✓ | ✓ | Both testable; RC Flow testing is more accessible to admins |
| Bulk / Headless Pricing API | ConnectAPI limited; mainly UI-driven | Pricing REST API & Connect API; headless-first design | ~ | ✓ | RC is designed for API-first integrations; CPQ bulk pricing requires workarounds |
2.4 Summary — Automation Architecture
- CPQ's QCP is powerful but requires JavaScript expertise, is hard to debug in production, and has no native unit test framework beyond Jest mocks.
- RC's Flow-based Pricing Procedures democratize pricing logic authorship — declarative steps are maintainable by senior admins, not just developers.
- For high-volume or headless scenarios (CPQ, B2B Commerce, partner portals), RC's API-first pricing architecture is the clear architectural winner.
- Both support external pricing engine integration, but RC's approach through named Flow elements is more auditable and easier to govern.
Configuration (Architect Setup Level)
Step-by-step setup procedures and complexity ratings for key pricing configurations
Products & Pricing → Discount Schedules → New; set Type=Volume, Discount Unit=Percent; add Tiers with LowerBound and Discount.
On Product2 SBQQ fields → set
SBQQ__DiscountedPriceScale__c or directly on Quote Line via Price Rule.Set
SBQQ__PricingMethod__c = Block on product; create Discount Schedule with Type=Slab; each tier is a flat per-unit price.Set
SBQQ__SubscriptionType__c = Renewable; enable SBQQ__SegmentedPricing__c; configure Segment Count, Segment Term, and Segment Label fields; requires CPQ+ license.New Price Rule → set Evaluation Order and Event; add Condition records (field/operator/value); add Action records (target field, source type, value).
Create custom Price Lookup object; create Price Rule with Source=Lookup; map output field to QuoteLine price field. Requires careful index planning for performance.
Write JS module; deploy via SFDX / Setup → Quote Calculator Settings; attach to org. JS must implement required interface methods. Requires CPQ+ and Apex test coverage for related code.
Enable multi-currency; configure dated exchange rates; ensure MDQ segments carry correct currency; Price Rule may be needed to freeze exchange rate at segment start date.
Revenue Lifecycle Management → Pricing Plans → New; set PlanType, EffectiveDate, Status=Active; associate with Pricebook or account segment.
Under Pricing Plan → Pricing Tiers → New; set LowerBound, UpperBound, AdjustmentType=PercentOff, AdjustmentValue; repeat per tier level.
New PriceAdjustmentSchedule; set AdjustmentMethod, priority, EffectiveDate; add child adjustment entries for each discount band.
Enable ramp on Cart Line product; configure RampInterval records (StartDate, EndDate, Quantity, Discount); RC can auto-generate from ramp template if configured.
Flow Builder → New Pricing Procedure Flow; add Get Records for PricingPlan; add Decision elements; add Loops for tiers; end with Update output pricing context variable. Register under Pricing Procedure setup.
Revenue Setup → Pricing Variables → New; set VariableName, DataType, Source (Field, Formula, Constant); bind to Pricing Procedure input parameters.
Create PricingPlanAssignment records linking Pricing Plan to Account (or Account Tier field value); requires Advanced RC; configure resolution priority when multiple plans match.
Create Named Credential; build Flow with HTTP callout element; parse response JSON; map price fields to pricing context output. Add error handling branch and fallback pricing logic.
MDQ vs RampInterval: Configuration Deep Dive
| Aspect | CPQ MDQ | RC RampInterval |
|---|---|---|
| Prerequisite | CPQ+ license; SBQQ__SegmentedPricing__c = true on product |
Revenue Cloud Advanced; ramp enabled on cart/product configuration |
| Segment Generation | Manual — rep enters each year's quantity; no auto-escalation formula | Auto-generate from ramp template; set escalation % per interval |
| Per-Segment Discount | Discount fields on each SBQQ__QuoteLineMDQ__c record |
Discount field directly on RampInterval |
| Per-Segment Price Rule | Price Rules can target MDQ line fields via condition on segment number | Pricing Procedure can branch logic per interval using Loop + Decision |
| TCV / ACV Calculation | Requires rollup formula on Quote; no native TCV field | Native TCV and ACV fields on Order and opportunity sync |
| Amendment / Co-Term | MDQ amendment creates co-term segments; complex edge cases with mid-year amendments | RampInterval-aware amendment recalculates remaining intervals cleanly |
| UI Experience | Tabular grid on Quote Line Editor; segment columns render per year | Ramp detail panel in Revenue Cloud UI; each interval editable inline |
| Bulk Ramp Creation | Data Loader import of SBQQ__QuoteLineMDQ__c records |
API POST /commerce/ramp-intervals or standard DML |
2.5 Summary — Configuration Complexity
- For basic tier pricing, both platforms are comparable (Low–Medium effort); CPQ has a more mature UI for discount schedule setup, while RC's UI is cleaner but newer.
- Ramp deals are significantly more powerful in RC — auto-generation, escalation formulas, and native TCV/ACV fields eliminate common CPQ workarounds.
- QCP deployment remains the highest-effort item in CPQ and the most common source of regression bugs; plan for robust Jest test suites if QCP is in scope.
- RC Pricing Procedures require Flow expertise; allocate Sprint time for procedure design, testing, and performance profiling against large quote volumes.
Customization (Common Additions)
Patterns for extending the pricing engine beyond out-of-the-box configuration
QCP JavaScript Customizations
- ✓onBeforeCalculate: Mutate quote/line context before CPQ pricing waterfall runs. Common use: populate lookup fields, default quantities.
- ✓onCalculate: Override calculated price completely. Common use: call external pricing engine, apply matrix pricing logic not expressible in rules.
- ✓onAfterCalculate: Post-processing after CPQ price calc. Common use: compute bundle totals, set custom display fields, validate margins.
- ✓onBeforePriceRules: Run logic before Price Rules evaluate. Common use: set prerequisite fields that Price Rules read as conditions.
- ~Async callouts in QCP: Supported via Promise chains but synchronous execution is unreliable; callout latency directly impacts quote UI responsiveness.
Revenue Cloud Flow-Based Extensions
- ✓Custom Pricing Procedure Steps: Add Flow sub-flows as discrete steps in the pricing pipeline; each step is independently versioned and testable.
- ✓Apex Action elements: Invoke
@InvocableMethodApex classes from Pricing Procedures for complex calculations not expressible in Flow. - ✓External HTTP Callout step: Use Flow's HTTP Callout element (Summer '23+) to call external pricing APIs with request/response transformation in Flow.
- ✓Platform Event trigger: Emit Platform Events from Pricing Procedure for async post-pricing actions (ERP notification, pricing log).
- ✓PricingContext manipulation: Read and write the standardized PricingContext output variable across all procedure steps; acts as shared state across the pipeline.
Custom Pricing Fields & Objects
- ✓Custom fields on QuoteLine: Add custom currency/number fields; surface in QCP or Price Rules; commonly used for margin %, effective rate, tiered price display.
- ✓Custom Price Lookup objects: Create custom objects as pricing matrices; Price Rules reference via lookup; design for SOQL index performance with large datasets.
- ✓Apex trigger on QuoteLine: Before/after triggers can supplement QCP; avoid double-write conflicts — use
SBQQ.TriggerControlto disable CPQ triggers during bulk ops. - ~Custom Visualforce/LWC on Quote: Possible but limited by CPQ's managed package UI frame; LWC components can be embedded in the Quote via custom buttons, not inline in line editor.
Custom Pricing Extensions
- ✓Custom Cart Line fields: Add fields to
CartItemorOrderProduct; expose in Pricing Procedure via Get Records or direct variable binding. - ✓Custom pricing matrix objects: Same pattern as CPQ — custom objects queried inside Pricing Procedure Flows; benefit: no namespace constraint on object naming.
- ✓Custom Ramp UI (LWC): RC exposes ramp data via standard APIs; build custom LWC ramp configurators embeddable in Experience Cloud or Salesforce UI.
- ✓Pricing API extensions: Extend RC pricing via custom REST resources calling the Pricing Procedure programmatically; enables headless storefronts and ERP integrations.
Common Anti-Patterns to Avoid
| Anti-Pattern | Platform | Risk | Preferred Alternative |
|---|---|---|---|
SOQL queries inside QCP onCalculate |
CPQ | Performance | Pre-load data in onBeforeCalculate; cache in QCP module-level variable |
| 100+ Price Rules with overlapping conditions | CPQ | Maintainability | Consolidate into fewer rules with formula conditions; move complex logic to QCP |
| Apex triggers modifying QuoteLines during quote save | CPQ | Data Integrity | Use SBQQ.TriggerControl.disable(); keep pricing in CPQ engine, not triggers |
| MDQ with >5 segments and per-segment Price Rules | CPQ | Performance | Limit rules to quote-level fields; push segment-specific logic to QCP onCalculate |
| Pricing Procedure with unbounded Get Records (no WHERE clause) | RC | Governor Limits | Always filter by product, plan, and effective date; add LIMIT clause |
| Sync HTTP callout in Pricing Procedure for every line | RC | Performance | Batch callout at quote level or cache external prices in custom object |
| Multiple competing Pricing Plans with equal priority | RC | Unpredictable Pricing | Always set unique priority values; document resolution order in pricing governance docs |
| Modifying RampInterval records in after-triggers | RC | Data Integrity | Use Pricing Procedure post-calculation hooks; avoid DML on RC platform objects in triggers |
CPQ-to-RC Migration: Pricing Customization Mapping
- QCP onCalculate → Pricing Procedure Flow with equivalent Decision + Formula elements; complex JS logic may need Apex Action wrapper.
- CPQ Price Rules → Pricing Procedure Decision elements or dedicated sub-Flow; maintain 1:1 mapping documentation during migration sprints.
- SBQQ__DiscountSchedule__c + Tiers → PriceAdjustmentSchedule + PricingTier records; direct data migration via Data Loader is feasible with field mapping.
- MDQ segments → RampInterval records; auto-generation in RC reduces manual data migration for standard ramp patterns.
- Custom QuoteLine fields → Custom CartItem / OrderProduct fields; verify field types match and update all Flows, reports, and page layouts referencing old fields.
2.6 Summary — Customization Architecture Guidance
- CPQ customization is mature but fragile — QCP JavaScript is the most common source of production pricing bugs; thorough Jest unit tests and staged deployments are mandatory.
- RC customization via Flow is more maintainable and accessible to senior admins, but requires disciplined Flow naming conventions, version control (SFDX), and performance testing at scale.
- For any new implementation: prefer declarative Pricing Plan + Tier configuration first, layer Pricing Procedures only for logic that cannot be expressed declaratively, and reserve Apex actions for genuine computational complexity.
- Governance recommendation: establish a Pricing Architecture Review Board — approve all new Price Rules (CPQ) or Pricing Procedure steps (RC) before production deployment to prevent rule explosion.
Pricing Procedures
The calculation engine, recipe layer, and context bridge that power Revenue Cloud pricing
The chef's step-by-step cooking instructions
A Flow-based orchestration pipeline that executes pricing logic as an ordered sequence of steps. Each step is an independent sub-flow responsible for one pricing concern (e.g., "Get List Price", "Apply Volume Tier", "Apply Partner Discount").
- Steps are sub-Flow elements — independently versioned and testable
- Shared state flows through a standardized
PricingContextoutput variable across all steps - Activation is date-effective — future pricing procedures can be staged before go-live
- Invocation occurs automatically when a seller adds a product to a quote, cart, or order; or via Pricing API for headless scenarios
- Versioning — multiple versions can coexist; only one is active per pricing context at a time
The pantry shelf map — telling the engine where to find ingredients
A standard configuration object that acts as a data dictionary for the pricing engine. It maps standard pricing components (like ListPrice, VolumeTierDiscount, or AttributeDiscount) to the specific Decision Tables or Decision Matrices in your Salesforce org.
- When the Pricing Procedure reaches a step that says "Get the List Price," it checks the active Pricing Recipe to find exactly which Decision Table to query
- Decision Tables — matrix-style lookup objects (e.g., product × quantity → price)
- Decision Matrices — multi-dimension lookups for more complex attribute-driven pricing
- One Recipe is active at a time per pricing context; switching recipes changes which tables the engine reads without rewriting procedure logic
- Supports A/B pricing experiments by maintaining multiple inactive recipes
The waiter — taking the order in, delivering the result back
Part of the Context Service, Context Mapping acts as a bridge between your actual Salesforce database objects and the pricing engine. The engine is intentionally object-agnostic — it can price Quotes, Orders, or custom objects equally well.
- Read Mapping (Input): Before calculation starts, reads fields from Quote, Quote Line, and Account (e.g.,
Customer_Tier__c = 'Gold') and feeds that data into the Pricing Procedure's input variables - Save Mapping (Output): Once calculation completes, writes calculated values (prices, adjustments, taxes) back to the correct fields on Quote Line or Order Product
- Mappings are configured per object type — the same Pricing Procedure can service Quote and Order without duplication
- Custom fields are fully supported on both read and write sides
- Context Mapping is the waiter. It takes the order from the customer (reads Quote data) and brings it to the kitchen. Once the meal is ready, it delivers the finished plate back to the table (writes calculated price to Quote Line).
- Pricing Recipe tells the chefs which pantry shelves to use. It maps each cooking step to the correct ingredient source (the right Decision Table in the database).
- Pricing Procedure is the chef's step-by-step recipe. It takes the raw ingredients (data from Context Mapping), follows the recipe (Decision Tables from Pricing Recipe), and produces the final net price.
CPQ vs. Revenue Cloud — Calculation Architecture
- Calculation order is fixed by CPQ's managed-package waterfall — no step reordering
- QCP JavaScript is the only extension point for custom logic between steps
- Price Rules read Conditions from Quote/Line fields — no explicit "context mapping" concept; fields are accessed directly
- No native Decision Table object — custom Apex or lookup objects required for matrix pricing
- A single Pricing Procedure equivalent doesn't exist; logic is distributed across Price Rules, QCP, and Discount Schedules
- Fully configurable waterfall — steps are reorderable, removable, and independently versioned
- Built on standard Salesforce Flow — no proprietary JS engine or sandbox restrictions
- Context Mapping decouples the engine from object structure — the same procedure can price Quotes and Orders without modification
- Decision Tables and Matrices are first-class objects — no custom Apex needed for matrix pricing
- Pricing Recipes allow swapping the entire "data source layer" without touching procedure logic — useful for testing, localization, or channel-specific pricing
In CPQ, pricing logic is distributed and implicit — spread across Price Rules, QCP, and Discount Schedules with no single orchestration layer. In Revenue Cloud, the Pricing Procedure is an explicit, ordered pipeline where every calculation step is visible, configurable, and independently testable. The separation of what to calculate (Pricing Procedure), where to find the data (Pricing Recipe + Decision Tables), and how to read/write Salesforce objects (Context Mapping) is the architectural differentiator — it makes RC pricing easier to maintain, extend, and hand off to non-developers.
RC 3.8 — Price Books in Revenue Cloud
Price Books are still a required standard object in Revenue Cloud — every Quote, Opportunity,
and Order carries a Pricebook2Id — but their role is narrower and more purposeful
than in CPQ. Understanding what Price Books should own versus what the Pricing Procedure
owns is the key architectural decision for any RC implementation.
Two-Layer Pricing Model
RC separates pricing concerns into two distinct layers. Mixing them is a common implementation anti-pattern that creates maintenance problems down the line.
- Object:
PricebookEntry.UnitPrice - What it controls: what you charge before any deal
- Scope: product availability + starting list price per market/currency
- Who sets it: Pricing Admin via standard Pricebook management
- Granularity: one price per product-pricebook combination
- Objects: Pricing Procedure Flow + Decision Tables
- What it controls: the deal on top of list price
- Scope: volume tiers, ramps, customer-segment discounts, partner rates
- Who sets it: Pricing Architects via Flow + Decision Table configuration
- Granularity: any combination of product, customer, volume, term
UnitPrice from the PricebookEntry,
then computes QuoteLineItem.NetUnitPrice.
Price Flow: From List to Net
| Stage | Object / Field | Owner | Description |
|---|---|---|---|
| 1. List Price | PricebookEntry.UnitPrice |
Price Book | Starting price for the product in this market |
| 2. Input Mapping | Context Mapping (Read) | Pricing Recipe | Pulls List Price + quote/product context into the pipeline |
| 3. Adjustments | Decision Tables (volume, segment, ramp) | Pricing Procedure | Applies discount or surcharge factors in sequence |
| 4. Output Mapping | Context Mapping (Save) | Pricing Recipe | Writes adjusted price back to the Quote Line |
| 5. Net Price | QuoteLineItem.NetUnitPrice |
RC Platform | What the customer actually pays |
Price Book Links Across the Quote-to-Cash Chain
The selected Price Book flows top-down through the deal chain and controls product availability at each step.
- Field:
Opportunity.Pricebook2Id - Rep selects or defaults to Standard Price Book
- Filters which products are available to add to a Quote
- Path 1 (Opportunity-First): Quote inherits this value
- Field:
Quote.Pricebook2Id - Path 1: inherited from Opportunity
- Path 2 (Quote-First): assigned directly on creation
- Path 3 (Self-Service): passed by the CC portal or headless API
- Field:
Order.Pricebook2Id - Flows from the Quote on conversion
- Cannot be changed after activation
- Must match the Quote's Price Book or conversion fails
Product Catalog vs. Price Book — Do They Need to Be 1:1?
No — and they shouldn't be. These are orthogonal concerns with different owners and different rates of change.
What you sell — product hierarchy, bundles, attributes, rules.
- Aligns to product lines or business units
- Examples: Enterprise SaaS, Professional Services, Add-ons
- Owned by Product Management
- Changes when you add/retire products or bundles
What you charge — list price in a given market or currency.
- Aligns to regions or currencies
- Examples: Standard (USD), EMEA (EUR), APAC
- Owned by Pricing / Finance
- Changes when list prices change (annual review cycle)
A single product can exist in multiple Price Books at different list prices. A Price Book can span products from multiple catalogs. Catalog proliferation does not solve pricing complexity — that belongs in Pricing Procedures, not in creating more catalogs or more price books.
Recommended Architecture
Typically 3–6 price books across the entire org. Nothing more.
All segment and deal logic lives here — not in separate price books.
CPQ vs. RC — Price Book Anti-Pattern to Avoid
| Dimension | CPQ Approach | RC Best Practice |
|---|---|---|
| Segment discounts | Separate "Partner Price Book" with baked-in 20% off list | Single Price Book + Decision Table step in Pricing Procedure |
| Volume tiers | CPQ Price Rules or Block Pricing (complex, brittle) | Volume tier Decision Table — readable, maintainable |
| Multi-currency | Currency-specific Price Books (proliferates books) | Org-level multi-currency + currency-scoped Price Books |
| Product availability | Controlled via Price Book and CPQ Product Rules | Controlled via Price Book + Product Catalog rules |
| Number of Price Books | Often 10–30+ as workaround for pricing logic | Typically 3–6, scoped to regions/currencies only |
| Auditability | Pricing logic scattered across Price Books, Price Rules, scripts | Pricing logic centralized in versioned Decision Tables |
Key Takeaway — 2.8
- Price Books are still required in RC — every Quote, Opportunity, and Order needs one. They gate product availability and provide the List Price starting value
- The Pricing Procedure is the true price engine — it reads List Price from the PricebookEntry and computes Net Price via Decision Tables. Price Books don't apply discounts; Pricing Procedures do
- Keep Price Books lean and regional — typically 3–6 across the org, scoped by currency or market. Never use them to encode segment or volume logic
- Product Catalog and Price Book are orthogonal — no 1:1 requirement. Catalogs align to product lines, Price Books align to markets. A product can appear in multiple Price Books
- The CPQ anti-pattern to avoid: in CPQ, teams created many Price Books to approximate discounting. In RC this is unnecessary — push all discount logic into Decision Tables where it is versioned, auditable, and business-user editable