cpq-performance-optimization
Use when diagnosing or resolving slow CPQ quote calculation, QLEx timeouts, or governor limit errors on large quotes. Trigger keywords: Large Quote Mode, QCP field declaration, quote calculation performance, SBQQ calculation timeout, async pricing. NOT for generic Apex performance tuning, CPQ pricing rule logic design, or billing engine performance.
Best use case
cpq-performance-optimization is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Use when diagnosing or resolving slow CPQ quote calculation, QLEx timeouts, or governor limit errors on large quotes. Trigger keywords: Large Quote Mode, QCP field declaration, quote calculation performance, SBQQ calculation timeout, async pricing. NOT for generic Apex performance tuning, CPQ pricing rule logic design, or billing engine performance.
Teams using cpq-performance-optimization should expect a more consistent output, faster repeated execution, less prompt rewriting, better workflow continuity with your supporting tools.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
- You already have the supporting tools or dependencies needed by this skill.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/cpq-performance-optimization/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How cpq-performance-optimization Compares
| Feature / Agent | cpq-performance-optimization | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Use when diagnosing or resolving slow CPQ quote calculation, QLEx timeouts, or governor limit errors on large quotes. Trigger keywords: Large Quote Mode, QCP field declaration, quote calculation performance, SBQQ calculation timeout, async pricing. NOT for generic Apex performance tuning, CPQ pricing rule logic design, or billing engine performance.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# CPQ Performance Optimization
This skill activates when a Salesforce CPQ implementation is experiencing slow or failing quote calculations, QLEx timeouts, or governor limit errors at scale. It covers the primary platform levers — Large Quote Mode, QCP field declaration discipline, and static resource architecture for large plugins — and explains the exact trade-offs each choice forces.
---
## Before Starting
Gather this context before working on anything in this domain:
- **Line count:** What is the typical and maximum quote line count for deals in this org? The synchronous CPQ calculation engine starts to produce governor pressure around 200–300 lines. Large Quote Mode is the primary lever past that threshold.
- **QCP field declarations:** Does the org use a Quote Calculator Plugin? If yes, pull the current `fieldsToCalculate` and `lineFieldsToCalculate` arrays. Undeclared fields cause silent null reads; overdeclared fields inflate the JSON payload sent to the calculation engine.
- **SBQQ__Code__c size:** Is the QCP code currently stored inline in `SBQQ__Code__c`? That field is hard-capped at 131,072 characters. Large plugins must use a Static Resource loaded via `eval()`.
- **Large Quote Mode status:** Check CPQ Package Settings > Large Quote Mode and the threshold value (default 100 lines). Confirm whether `SBQQ__LargeQuote__c` on the Account record is also in use — the mode can be toggled at the account level independently of the package setting.
- **Calculate Quote API usage:** If the org uses the `SBQQ.ServiceRouter` calculate API in Apex batch jobs, understand that it runs at async speed — it does not bypass governor limits and is not a substitute for Large Quote Mode on large quotes.
---
## Core Concepts
### Large Quote Mode
Large Quote Mode shifts quote calculation from a synchronous in-browser model to an asynchronous server-side model. When enabled and the quote line count exceeds the configured threshold, the CPQ engine queues a server-side calculation job and returns control to the user immediately. The QLE displays a "calculating" status indicator; reps cannot save or submit the quote until calculation completes.
This is a UX-breaking change. Reps accustomed to immediate recalculation will see a delay and a status indicator they have not seen before. Enablement without user communication causes support tickets. The threshold must be tuned: too low and reps are interrupted on medium quotes; too high and large quotes still hit governor limits.
Large Quote Mode is controlled at two levels: (1) the CPQ Package Settings field "Large Quote Mode" with a line count threshold, and (2) the `SBQQ__LargeQuote__c` checkbox on the Account record, which forces async mode for all quotes on that account regardless of line count. Both controls must be considered.
### QCP Field Declaration
A Quote Calculator Plugin must declare every field it intends to read or write in two arrays: `fieldsToCalculate` (quote header fields) and `lineFieldsToCalculate` (quote line fields). CPQ uses these declarations to build the JSON payload sent to the plugin; fields not declared are excluded from the payload entirely.
Two failure modes exist:
- **Underdeclaring:** The plugin reads a field that is not declared. The field value is `null` in the payload. The plugin operates on null silently — no error is thrown, pricing logic produces wrong results, and the bug is hard to diagnose.
- **Overdeclaring:** Fields are declared "just in case." Each additional field increases JSON payload size, calculation API call size, and round-trip time. On 200+ line quotes the overhead compounds.
The correct discipline is to declare exactly the fields the plugin reads or writes — no more, no less. This requires auditing the plugin code against the declaration arrays.
### SBQQ__Code__c Size Limit and Static Resource Architecture
The `SBQQ__Code__c` field on the `SBQQ__CustomScript__c` object stores QCP JavaScript inline. The field is a Long Text Area capped at 131,072 characters. Modern QCPs that include helper functions, pricing tables, or complex bundle logic routinely exceed this limit.
The correct architecture for large plugins is to store the JavaScript in a Static Resource and load it at runtime using `eval()`. The inline `SBQQ__Code__c` field holds only the bootstrap code that fetches and evaluates the static resource. This approach has no practical code-size limit (Static Resources support up to 5 MB per file) but requires the static resource to be deployed as part of every plugin release — a build and deployment discipline change that must be documented.
### Calculate Quote API Is Not a Performance Bypass
The `SBQQ.ServiceRouter` Calculate Quote API (`SBQQ.ServiceRouter.load('SBQQ.QuoteAPI.Calculate', ...)`) runs quote calculation programmatically. It is commonly mistaken for a high-performance batch path. It is not — it runs at the same async speed as the UI path and is subject to the same governor limits on large quotes. Enabling Large Quote Mode affects both the UI and the API paths. The API is useful for automation and integration, not for circumventing calculation limits.
---
## Common Patterns
### Pattern 1: Enabling Large Quote Mode With UX Coordination
**When to use:** Quote line counts frequently exceed 150–200 lines, causing QLEx timeouts or governor limit errors during calculation.
**How it works:**
1. Navigate to CPQ Package Settings > Large Quote Options.
2. Set "Large Quote Mode" to Enabled.
3. Set the threshold to the line count above which async mode should activate (start with 150 if unsure; tune based on governor error frequency).
4. Optionally enable `SBQQ__LargeQuote__c` on specific accounts where all quotes should be async regardless of line count.
5. Update the QLE save button label or add a custom notification to inform reps that calculation is running asynchronously.
6. Add a process to monitor Apex jobs for failed calculation queue entries.
**Why not the alternative:** Leaving synchronous mode in place and trying to optimize Apex limits on the calculation path (adding custom indexes, trimming price rules) provides incremental gains but cannot overcome the fundamental CPU and SOQL limits that fire at scale.
### Pattern 2: Auditing and Correcting QCP Field Declarations
**When to use:** QCP is returning unexpected null values for fields, or calculation is slower than expected on mid-size quotes (50–150 lines).
**How it works:**
1. Extract the current `fieldsToCalculate` and `lineFieldsToCalculate` arrays from the QCP source.
2. Search the plugin code for every field API name referenced in `record.*` or `quoteModel.*` expressions.
3. Build a new declaration list containing exactly those fields.
4. Compare old list vs new list: remove any field not referenced; add any field referenced but missing.
5. Deploy the updated plugin to a sandbox and validate with a representative large quote that all pricing logic produces correct results.
6. Monitor calculation time on a set of test quotes before and after to confirm payload reduction.
**Why not the alternative:** Declaring all fields "to be safe" is a common shortcut that degrades performance at scale and masks logic bugs where the plugin accidentally depends on fields that should not be in scope.
### Pattern 3: Migrating QCP Code to Static Resource
**When to use:** `SBQQ__Code__c` is approaching or has exceeded 131,072 characters, or deployment of plugin updates is failing due to field size limits.
**How it works:**
1. Extract the full plugin JavaScript into a new Static Resource (e.g., `QuoteCalculatorPlugin.js`).
2. In `SBQQ__Code__c`, retain only the bootstrap loader:
```javascript
// Bootstrap: load QCP from Static Resource
var resourceUrl = '/resource/QuoteCalculatorPlugin';
var xhr = new XMLHttpRequest();
xhr.open('GET', resourceUrl, false);
xhr.send(null);
eval(xhr.responseText);
```
3. Include the Static Resource in every Salesforce DX package version and change set that includes a plugin update.
4. Document the deployment order: Static Resource must be deployed before or alongside the `SBQQ__CustomScript__c` record.
5. Validate in sandbox: open the QLE on a test quote and confirm the plugin loads correctly via browser console.
**Why not the alternative:** Splitting logic across multiple inline scripts or compressing code to stay under the character limit produces unmaintainable code and does not scale.
---
## Decision Guidance
| Situation | Recommended Approach | Reason |
|---|---|---|
| Quotes regularly exceed 200 lines with timeout errors | Enable Large Quote Mode at 150-line threshold | The synchronous engine cannot handle this scale; async is the only reliable path |
| QCP returns wrong prices silently on some fields | Audit and correct field declarations | Undeclared fields return null silently; no error surface |
| QCP code exceeds or approaches 131,072 chars | Migrate to Static Resource + eval() bootstrap | Hard field cap; static resource scales to 5 MB |
| Batch job re-prices all quotes nightly | Use Calculate Quote API with Large Quote Mode enabled | API is the correct programmatic path; Large Quote Mode still applies |
| Medium quotes (50-150 lines) calculate slowly | Audit field declarations and price rule count | Over-declared fields and excessive lookup price rules are the primary cause |
| Account always has large quotes regardless of line count | Set SBQQ__LargeQuote__c on Account | Account-level flag forces async for all quotes on that account |
---
## Recommended Workflow
Step-by-step instructions for an AI agent or practitioner working on this task:
1. **Establish baseline:** Record current quote line counts, average calculation time, and frequency of governor errors. Identify the threshold at which errors begin. Pull CPQ Package Settings to confirm current Large Quote Mode status and threshold value.
2. **Audit QCP field declarations:** If a QCP is in use, compare declared fields against all field references in plugin code. Produce a corrected declaration list. Fix underdeclared fields immediately — they produce silent wrong prices.
3. **Assess SBQQ__Code__c size:** Check the current character count of `SBQQ__Code__c`. If it exceeds 100,000 characters, plan a migration to Static Resource architecture before the next plugin update.
4. **Enable Large Quote Mode if needed:** If quotes exceed 150 lines and governor errors are occurring, enable Large Quote Mode. Set the threshold conservatively and document the async UX change for end users and sales operations.
5. **Communicate UX change to reps:** Prepare user guidance describing the async calculation indicator, expected wait time, and that quotes cannot be saved during active calculation. Coordinate with the sales ops team before production enablement.
6. **Validate in sandbox:** Run a set of representative large quotes through the full calculation cycle. Confirm correct prices, no null field errors, and successful save. Check the Apex job queue for any failed calculation jobs.
7. **Monitor in production:** After enablement, monitor Apex job queue for calculation failures, track average calculation time, and confirm governor error frequency drops. Tune the Large Quote Mode threshold if necessary.
---
## Review Checklist
Run through these before marking work in this area complete:
- [ ] Large Quote Mode threshold is set and tuned to the actual quote volume distribution (not left at the default 100 without review)
- [ ] QCP field declarations match exactly the fields the plugin reads and writes — no over-declaration, no under-declaration
- [ ] SBQQ__Code__c character count is below 131,072; if approaching the limit, Static Resource migration is planned
- [ ] Sales reps and sales operations have been informed of async calculation UX change before production enablement
- [ ] Apex job queue monitoring is in place for failed calculation jobs
- [ ] Calculate Quote API usage in batch jobs is accounted for — Large Quote Mode affects the API path as well
---
## Salesforce-Specific Gotchas
Non-obvious platform behaviors that cause real production problems:
1. **Large Quote Mode Is Not Quote-Level** — It is controlled by the CPQ Package Settings threshold and the `SBQQ__LargeQuote__c` Account field. There is no per-quote toggle. Turning it on affects all quotes above the threshold across the org.
2. **Undeclared QCP Fields Return Null, Not an Error** — If a field is missing from `fieldsToCalculate` or `lineFieldsToCalculate`, the plugin receives `null` for that field. No exception is thrown. Pricing logic silently computes wrong values. This is the most common source of subtle QCP bugs.
3. **Calculate Quote API Shares Governor Limits** — Using the `SBQQ.ServiceRouter` calculate API in an Apex batch job does not bypass CPQ calculation limits. It runs at the same speed and under the same governor constraints as the UI path.
---
## Output Artifacts
| Artifact | Description |
|---|---|
| Corrected QCP field declaration list | Pruned `fieldsToCalculate` and `lineFieldsToCalculate` arrays ready to deploy |
| Large Quote Mode configuration record | Recommended threshold value and Account-level flag decisions |
| Static Resource bootstrap loader | Minimal `SBQQ__Code__c` content for large plugin architecture |
| UX communication plan | End-user guidance for async calculation mode |
---
## Related Skills
- `data/cpq-data-model` — CPQ object model and field relationships; foundational for understanding which fields to declare in QCP
- `apex/cpq-api-and-automation` — ServiceRouter calculate API, async quote calculation patterns, and batch re-pricing
- `architect/cpq-architecture-patterns` — System-level CPQ architecture decisions including Large Quote Mode placement in the overall solution design
- `admin/cpq-pricing-rules` — Price rule volume and lookup query counts are a secondary performance factor after line count
---
## Official Sources Used
- Large Quote Performance Settings — https://help.salesforce.com/s/articleView?id=sf.cpq_large_quote.htm&type=5
- CPQ Quote Calculation Stages — https://help.salesforce.com/s/articleView?id=sf.cpq_calculation_stages.htm&type=5
- JavaScript Quote Calculator Plugin (QCP) — https://developer.salesforce.com/docs/atlas.en-us.cpq_dev_guide.meta/cpq_dev_guide/cpq_dev_jsqcp_parent.htm
- Salesforce CPQ Developer Guide: Calculate Quote API — https://developer.salesforce.com/docs/atlas.en-us.cpq_dev_guide.meta/cpq_dev_guide/cpq_dev_quote_calculator.htmRelated Skills
omnistudio-performance
Use when diagnosing or improving runtime performance in OmniStudio assets: slow OmniScripts, Integration Procedures with high latency, DataRaptor caching, excessive API call counts, FlexCard rendering delays, or async IP fire-and-forget patterns. Triggers: 'OmniScript slow', 'Integration Procedure timeout', 'DataRaptor cache', 'FlexCard loading too long', 'reduce API calls OmniStudio'. NOT for LWC performance outside of OmniScript runtime (use lwc-performance skill). NOT for OmniScript step design or journey UX (use omniscript-design-patterns skill).
dataraptor-transform-optimization
Use when DataRaptor Transform operations are slow, hit governor limits, or use Apex where formula fields would suffice. Covers formula vs Apex expressions, bulk transform sizing, and chained transform composition. Triggers: 'dataraptor transform slow', 'dataraptor formula vs apex', 'dataraptor bulk transform', 'dr governor limit'. NOT for DataRaptor Extract or Load performance.
lwc-performance
Use when designing or reviewing Lightning Web Components for slow initial load, heavy rerenders, large-list rendering, payload reduction, and lazy instantiation choices such as `lwc:if`, tabs, or dynamic components. Triggers: 'slow lwc', 'rerenders too much', 'key index', 'dynamic import', 'large list lag'. NOT for wire-service data-source selection when provisioning strategy is the only question or for mobile/offline-specific tuning.
lwc-performance-budgets
Set and enforce performance budgets for Lightning Web Components: bundle-size limits per component, LCP/INP field targets, wire-adapter count caps, and CI-gate configuration using Lighthouse or webpagetest. Trigger keywords: lwc performance budget, bundle size limit, lcp budget, lighthouse ci, lwc size gate. Does NOT cover runtime optimization techniques, Lightning page tuning, or general LCP causes (see lwc-performance).
flow-performance-optimization
Tune Flow runtime performance: pick Before-Save over After-Save, consolidate Get Records, eliminate loop-DML, cache lookups, split with Scheduled Paths, and measure actual runtime. Covers benchmarking methodology, profiling tools, and the 80/20 wins. NOT for governor-limit math (use flow-governor-limits-deep-dive). NOT for LDV strategy (use flow-large-data-volume-patterns).
flow-get-records-optimization
Optimize Get Records elements in Flow: filter sharpness, field selection, sort-and-limit placement, caching via formula resources, and avoiding repeated queries in loops. Trigger keywords: get records, flow soql, flow query limit, flow performance, record lookup. Does NOT cover Apex SOQL, Data Cloud queries, or external object lookups.
performance-testing-salesforce
Use when planning or executing load tests, stress tests, or performance benchmarks against a Salesforce org. Covers Salesforce Scale Test, third-party tools (JMeter, BlazeMeter, k6), API throughput testing, Experience Page Time (EPT) measurement, and sandbox sizing for performance work. Triggers: 'load test Salesforce org', 'Scale Test Full Copy sandbox', 'EPT optimization', 'API concurrency limits', 'JMeter Salesforce performance'. NOT for Apex unit test performance assertions, LWC Jest tests, query optimization (see data/soql-query-optimization), or NFR definition (see architect/nfr-definition-for-salesforce).
soql-query-optimization
Use when a SOQL query is running slowly, causing timeouts, or returning UNABLE_TO_LOCK_ROW errors in large data volume orgs. Covers index-aware query writing, selectivity rules, the Query Plan tool, skinny tables, and dynamic field-set queries. Triggers: slow soql query, query timeout, non-selective query, query plan tool, index usage, soql optimization, large object performance. NOT for Apex CPU or heap governor limit issues (use apex-cpu-and-heap-optimization) or for writing basic SOQL (use soql-fundamentals).
sharing-recalculation-performance
Plan, batch, and monitor Salesforce sharing recalculation jobs — including OWD changes, sharing rule add/remove, role hierarchy restructuring, and Apex managed share rebuild — to avoid multi-hour background jobs and data-access blackouts. NOT for diagnosing data-skew root causes (use admin/data-skew-and-sharing-performance), NOT for designing the sharing model itself (use admin/sharing-and-visibility), and NOT for Apex managed sharing row-cause creation (use apex/apex-managed-sharing).
analytics-dataset-optimization
Use this skill when tuning CRM Analytics dataset performance through field selection, date granularity choices, dataset splitting strategy, and run-budget optimization. Trigger keywords: dataset too many fields, SAQL timeseries slow, epoch vs date storage, dataset field count limit, dataset partition, split dataset by year, CRM Analytics performance tuning. NOT for SOQL optimization, Salesforce report tuning, Data Cloud segmentation performance, or choosing between analytics tools.
license-optimization-strategy
Auditing, right-sizing, and reclaiming Salesforce licenses to reduce cost and ensure compliant allocation. Trigger keywords: license audit, license cost reduction, unused licenses, permission set license, login-based license, inactive users, license reclamation, right-size licenses. NOT for provisioning net-new licenses (contact AE). NOT for Experience Cloud community license troubleshooting. NOT for permission set assignment logic outside of license gating.
fsl-optimization-architecture
Use this skill when designing or evaluating the FSL scheduling engine architecture: optimization mode selection (Global/In-Day/Resource/Reshuffle), ESO adoption strategy, territory sizing for optimization, and fallback planning. Trigger keywords: FSL optimization engine, ESO enhanced scheduling, global optimization timeout, in-day optimization, OAAS architecture, territory optimization design. NOT for admin-level scheduling policy configuration, scheduling rule setup in Setup, or per-appointment scheduling API calls (covered by apex/fsl-scheduling-api).