Schema describe call inside a loop

ID

apex.performance.eager_describe

Severity

info

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Performance

Language

Apex

Description

Reports a getDescribe() or getGlobalDescribe() call inside a for, while or do loop.

Rationale

A describe call is not free: the platform builds the metadata result on demand, and getGlobalDescribe() builds one for every object in the org. Inside a loop that cost is paid per iteration, in CPU time that counts toward the 10-second synchronous limit - and the result is identical every time, because object metadata cannot change during a transaction. The loop that runs over five records in a test runs over two hundred in a trigger, which is where the CPU time limit exceeded arrives, with no line number pointing at the describe.

The following code illustrates the pattern detected by this rule:

public class FieldWalker {

    public void describeInLoop(List<String> objectNames) {
        for (String name : objectNames) {
            // FLAGGED: Schema describe call inside a loop
            Map<String, Schema.SObjectField> fields = Schema.getGlobalDescribe().get(name).getDescribe().fields.getMap();
            System.debug(fields.size());
        }
    }

    public void describePerField(List<String> fieldNames) {
        for (Integer i = 0; i < fieldNames.size(); i++) {
            // FLAGGED: Schema describe call inside a loop
            Schema.DescribeFieldResult f = Account.SObjectType.getDescribe().fields.getMap().get(fieldNames[i]).getDescribe();
            System.debug(f.getLabel());
        }
    }

    public void describeOnce(List<String> fieldNames) {
        Map<String, Schema.SObjectField> fields = Account.SObjectType.getDescribe().fields.getMap();
        for (String name : fieldNames) {
            System.debug(fields.get(name));
        }
    }

    public void noDescribe(List<Account> accounts) {
        for (Account a : accounts) {
            System.debug(a.Name);
        }
    }
}

Remediation

Hoist the describe above the loop and keep the result in a local, or cache it in a static map for the transaction. Where only the field token is needed, Account.Name.getDescribe() or the SObjectType token is cheaper than walking getGlobalDescribe().

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved