Cursor fetch asks for more than 1000 rows at once

ID

apex.performance.cursor_fetch_chunk_size

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Performance

Language

Apex

Description

Reports a fetch(position, count) call on a Database cursor whose row count is above 1000 (fixed threshold).

Rationale

A cursor exists so that a large result set can be walked without holding it in memory, and a fetch that asks for thousands of rows gives that back: the records land in the heap all at once, and a wide object will pass the 6 MB synchronous heap limit long before the row count looks unreasonable. The failure is a LimitException in the middle of a walk that has already committed earlier chunks, so the job stops half-applied and the restart position is whatever the last successful fetch happened to be.

The following code illustrates the pattern detected by this rule:

public class LedgerWalk {

    public void walkTooMuch(Database.Cursor cursor) {
        // FLAGGED: Cursor fetch asks for more than 1000 rows at once
        List<Ledger__c> rows = cursor.fetch(0, 2000);
        System.debug(rows.size());
    }

    public void walkFarTooMuch(Database.Cursor cursor, Integer position) {
        // FLAGGED: Cursor fetch asks for more than 1000 rows at once
        List<Ledger__c> rows = cursor.fetch(position, 5000);
        System.debug(rows.size());
    }

    public void walkInChunks(Database.Cursor cursor, Integer position) {
        List<Ledger__c> rows = cursor.fetch(position, 200);
        System.debug(rows.size());
    }

    public void walkOne(Database.Cursor cursor) {
        List<Ledger__c> rows = cursor.fetch(0, 1);
        System.debug(rows.size());
    }
}

Remediation

Fetch in chunks the transaction can hold - a few hundred rows is the usual working figure - and loop until the cursor is exhausted, releasing each chunk before fetching the next. Size the chunk against the width of the object, not against the row limit.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved