Verdict
Use search.lookupFields by default when you are only reading a small number of fields. Reach for record.load only when you truly need full record behavior or intend to modify and save.
Comparison Table
| Criterion | Option A | Option B | Recommendation |
|---|---|---|---|
| Governance cost | Typically far cheaper for lightweight reads. | Expensive if used as a reflex. | lookupFields wins for simple reads. |
| API surface | Limited to returned field values. | Full record interaction. | record.load only when you need the full surface area. |
| Loop safety | Safer for repeated execution. | Can become a governance trap quickly. | lookupFields in loops unless proven insufficient. |
| Mutation path | Not the right tool for mutation. | Natural fit when save follows. | record.load when the read is part of an update workflow. |
Decision Criteria
- Whether you only need a handful of fields
- Whether sublists or full record APIs are required
- Whether a save path follows the read
- How often this operation runs inside loops or batch jobs
Choose search.lookupFields When
The cheapest and usually correct option for lightweight reads.
Good Fit
- You need one to three body fields
- The call sits inside a loop or high-frequency execution path
- You want the minimum viable read cost
Avoid It When
- You need sublist data or full record APIs
- You are about to mutate and save the record
- The read depends on behaviors not exposed through lookupFields
Choose record.load When
Correct when you need full record context, not just field values.
Good Fit
- You need to inspect or manipulate the full record
- A save operation follows shortly after
- You need record APIs beyond simple field lookup
Avoid It When
- You only need a couple of body fields
- The call is repeated across large data sets
- Governance is already a constraint in this execution path
The Most Common Governance Leak
I see this pattern constantly: a developer needs one field, reaches for record.load because it is familiar, and then repeats that choice inside a loop. Individually the call feels harmless. At scale it becomes the quiet reason the script no longer finishes cleanly.
const values = search.lookupFields({
type: search.Type.SALES_ORDER,
id: orderId,
columns: ['entity', 'status']
});Default bias
If you are only reading, your first thought should be lookupFields. Make record.load prove that it is necessary.
Governance and Performance
Governance
This is the kind of small decision that becomes a site-wide performance problem. The wrong choice multiplied by thousands of iterations is how ordinary scripts turn into governance incidents.
Performance
The real optimization is not micro-benchmarking a single call. It is removing unnecessary full-record loads from hot paths.
Frequently Asked Questions
- Should I replace every record.load with lookupFields?
- No. Replace the loads that exist only to read a few fields. Keep record.load when you need full record behavior or a save path is part of the same operation.
- Does this choice really matter outside large batches?
- Yes, because hot paths compound. A small inefficiency repeated across user events, scheduled runs, and integrations turns into a persistent governance tax.