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).

Best use case

flow-performance-optimization is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

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).

Teams using flow-performance-optimization should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

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

$curl -o ~/.claude/skills/flow-performance-optimization/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/flow/flow-performance-optimization/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/flow-performance-optimization/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How flow-performance-optimization Compares

Feature / Agentflow-performance-optimizationStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

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).

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

# Flow Performance Optimization

## Core concept — the performance hierarchy

Flow performance is dominated by a small set of decisions, ranked by impact:

1. **Before-Save vs After-Save** (biggest lever — 10-50× swing for field derivation).
2. **Hoisting DML and SOQL out of loops** (10-200× swing depending on loop size).
3. **Consolidating multiple Get Records into one** (2-5× swing).
4. **Caching lookup data in session variables** (2-10× swing for repeated reads).
5. **Splitting synchronous work into Scheduled Paths** (removes cost from user-facing save).
6. **Reducing CPU-heavy Decision/Assignment chains** (5-20% swing, rarely the biggest lever).

Optimize in this order. Tuning (6) when (1) is still suboptimal is wasted effort.

## Recommended Workflow

1. **Measure first.** Don't optimize without a baseline. Use Test.startTest/stopTest in Apex to capture `Limits.getCpuTime()` before and after the flow fires.
2. **Identify the dominant cost.** SOQL count? DML count? CPU time? Heap?
3. **Apply the highest-impact lever** for that dominant cost, per the hierarchy above.
4. **Re-measure.** If the cost is still dominant, iterate; if another cost now dominates, shift focus.
5. **Stop when the flow meets SLA with 30% headroom.** Premature micro-optimization has diminishing returns.

## Key patterns

### Pattern 1 — Before-Save over After-Save for field derivation

Before-Save field assignments cost zero extra DML. The same assignment in After-Save causes the record to be written twice (once for the user's save, once for the flow's update).

Migration:
- After-Save Flow that sets `Region__c` on Account → change entry to Before-Save.
- Verify no DML elements remain (Before-Save doesn't support them).
- Expected win: 90% reduction in flow cost.

### Pattern 2 — Hoist DML out of a loop

```
BEFORE:
[Loop over Cases]
  └── [Update Case.Priority = 'High']   ← 1 DML per iteration

AFTER:
[Assignment: collect Cases with new Priority into a collection]
[Loop over Cases]
  └── [Assignment: priorityCollection.add({!Case with Priority='High'})]
[Update Records (collection)]            ← 1 DML total
```

Impact: 200 iterations = 200 DML statements → 1 DML statement. Often the single biggest win in a bulk-sensitive flow.

### Pattern 3 — Consolidate Get Records

```
BEFORE:
[Get Records: Contacts where AccountId = X]
[Get Records: Opportunities where AccountId = X]
[Get Records: Cases where AccountId = X]
=> 3 SOQL

AFTER (if single relation direction is acceptable):
[Get Records: Account where Id = X, with nested children Contacts, Opportunities, Cases]
=> 1 SOQL with traversal via Get-Related-Records sub-query
```

Flow Get Records supports querying related records in one go via the child relationship picker. Use it.

### Pattern 4 — Cache repeated lookups

```
BEFORE:
[Loop over Orders]
  └── [Get Records: Shipping Rate where PostalCode = {!Order.ShipZip}]    ← SOQL per iteration

AFTER:
[Outside loop: Get Records: all Shipping Rates for the zips in the batch]
[Assignment: build Map<String, ShippingRate> by PostalCode]
[Loop over Orders]
  └── [Assignment: rate = map[Order.ShipZip]]
```

Flow doesn't have a Map primitive, but you can simulate with a Collection and filter-by-equality inside the loop. Better: push the lookup to an Apex invocable that returns a bulked result.

### Pattern 5 — Scheduled Path for non-critical work

Flow fires on save. It does 4 things: (a) derive a field, (b) create a Task, (c) send an email, (d) call a vendor API.

- (a) stays inline (Before-Save).
- (b, c) stay inline (After-Save, cheap).
- (d) moves to Scheduled Path +0 (async; callout allowed; won't block the save).

User-perceived save time drops from 2s to 0.5s.

### Pattern 6 — Reduce wasteful sObject loading

A Get Records element that selects `SELECT *` equivalent returns all fields. Flow's default is to fetch every field. Tune by explicitly listing the fields needed — both for heap and CPU savings.

## Benchmarking methodology

```apex
@IsTest
static void benchmarkFlow() {
    List<Account> accounts = createBulkFixture(200);

    Long start = Limits.getCpuTime();
    Integer startSoql = Limits.getQueries();
    Integer startDml = Limits.getDMLStatements();

    Test.startTest();
    insert accounts;
    Test.stopTest();

    System.debug('CPU: ' + (Limits.getCpuTime() - start) + 'ms');
    System.debug('SOQL: ' + (Limits.getQueries() - startSoql));
    System.debug('DML: ' + (Limits.getDMLStatements() - startDml));
}
```

Run before and after each optimization; commit measurements alongside the code change.

## Bulk safety

Performance optimization and bulk safety are the same discipline. Every pattern in this skill is about scaling gracefully; every skipped optimization is a future limit exception.

## Error handling

Optimization sometimes changes error surface:
- Moving work to a Scheduled Path means errors no longer roll back the user's save — they become log records instead.
- Consolidating Get Records into one means a single null-result affects downstream logic; handle with Decision elements.

Test both success and fault paths after every optimization.

## Well-Architected mapping

- **Performance** — the whole skill is about performance. Each pattern addresses one of the six highest-impact levers.
- **Reliability** — a performant flow survives load spikes. An un-tuned flow works in test, breaks on the first busy day.

## Gotchas

See `references/gotchas.md`.

## Testing

Every optimization should ship with a benchmark delta in the PR description:

```
Before: 200-record insert = 3200ms CPU, 15 SOQL, 8 DML
After:  200-record insert = 1100ms CPU, 4 SOQL, 2 DML
Reduction: 66% CPU, 73% SOQL, 75% DML
```

## Official Sources Used

- Salesforce Developer — Flow Performance Optimization: https://developer.salesforce.com/blogs/2022/07/flow-performance-optimization
- Salesforce Help — Flow Limits and Considerations: https://help.salesforce.com/s/articleView?id=sf.flow_considerations_limit.htm
- Salesforce Help — Before-Save vs After-Save Flows: https://help.salesforce.com/s/articleView?id=sf.flow_concepts_trigger.htm
- Salesforce Architects — Performance Engineering: https://architect.salesforce.com/

Related Skills

ip-range-and-login-flow-strategy

8
from PranavNagrecha/AwesomeSalesforceSkills

Design and implement Salesforce Login Flows (Screen Flows assigned to profiles or Experience Cloud sites) that run post-authentication to enforce conditional MFA, IP-based branching, terms-of-service acceptance, or user data collection. Covers Login Flow creation in Flow Builder, profile/site assignment, IP-aware decision logic, and ConnectedAppPlugin extension points. NOT for static IP allowlisting or profile Login IP Ranges (see network-security-and-trusted-ips), org-wide session policies, or SSO/SAML IdP configuration.

customer-data-request-workflow

8
from PranavNagrecha/AwesomeSalesforceSkills

Implement GDPR/CCPA data subject rights (access, deletion, rectification) using Salesforce Privacy Center and/or custom workflow. NOT for general backup or org-level data retention policy.

omnistudio-vs-flow-decision

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when choosing between OmniStudio (OmniScript / Integration Procedure / FlexCard / DataRaptor) and Flow / Screen Flow / Apex for a given capability. Triggers: 'omnistudio or flow', 'omniscript vs screen flow', 'integration procedure vs subflow', 'flexcard vs lightning page'. NOT for general automation selection across Workflow/Process Builder/Apex (see automation-selection tree).

omnistudio-performance

8
from PranavNagrecha/AwesomeSalesforceSkills

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

8
from PranavNagrecha/AwesomeSalesforceSkills

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

8
from PranavNagrecha/AwesomeSalesforceSkills

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

8
from PranavNagrecha/AwesomeSalesforceSkills

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).

lwc-in-flow-screens

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when building, reviewing, or troubleshooting a custom Lightning Web Component that runs inside a Flow screen element, covering @api props exposed to Flow, FlowAttributeChangeEvent for output, validate() for user input validation, and flow navigation events. Triggers: 'lwc in flow screen', 'FlowAttributeChangeEvent', 'flow screen component not updating', 'flow validate method', 'flow navigation from lwc'. NOT for custom property editors (use custom-property-editor-for-flow), NOT for embedding a flow inside an LWC (use flow/screen-flows), NOT for auto-launched flows.

custom-property-editor-for-flow

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when building or reviewing an LWC Custom Property Editor for Flow screen or action configuration, including the `configurationEditor` metadata hook, builder-side APIs, validation, and value-change events. Triggers: 'custom property editor', 'Flow configuration editor', 'builderContext', 'inputVariables', 'configurationEditor'. NOT for ordinary runtime screen-component behavior when no Flow Builder design-time customization is involved.

slack-workflow-builder

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when designing or troubleshooting Slack Workflow Builder workflows that call Salesforce — especially the Salesforce connector step Run a Flow, mapping inputs/outputs, handling failures, and understanding limits. Triggers on: Slack Workflow Builder Salesforce, Run a Flow from Slack, autolaunched flow from Slack, Slack automation calling Salesforce. NOT for Salesforce Flow Builder tutorials unrelated to Slack (use flow skills), not for Flow Core Actions that send Slack messages from Salesforce (use flow-for-slack), not for initial org-to-workspace connection (use slack-salesforce-integration-setup), and not for building custom Slack apps outside Workflow Builder.

oauth-flows-and-connected-apps

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when choosing or reviewing Salesforce OAuth flows and connected-app policy for integrations, including client credentials, JWT bearer, authorization code, device flow, scopes, and token lifecycle controls. Triggers: 'OAuth flow', 'connected app', 'client credentials', 'JWT bearer', 'refresh token', 'integration user'. NOT for record-level sharing design or for simple Named Credential usage when the auth-flow decision is already settled.

workflow-rule-to-flow-migration

8
from PranavNagrecha/AwesomeSalesforceSkills

Migrate Workflow Rules to record-triggered Flows: field update mapping, email alert migration, outbound message alternatives using Flow Core Actions, time-based workflow replacement with Scheduled Paths. NOT for Process Builder migration (use process-builder-to-flow-migration), NOT for building new flows from scratch.