Mastering Salesforce Apex Cursors: Scalable High-Volume Data Processing in Spring ’26

The Evolution of Large-Scale Data Handling in Apex

For years, Salesforce developers have relied on Batch Apex or SOQL offsets to handle large datasets. However, these methods often come with significant overhead, state management complexity, or strict limits (like the 2,000-record offset limit). With the Spring ’26 release, Apex Cursors have moved to General Availability (GA), introducing a high-performance, stateless way to navigate up to 50 million records efficiently.

What are Apex Cursors?

Apex Cursors provide a server-side pointer to a query result set. Unlike traditional SOQL, which retrieves all results at once or requires manual batching, a cursor allows you to fetch chunks of data on demand. This is particularly transformative for long-running processes where you need to maintain a position across different execution contexts or transactions.

Key Technical Capabilities

  • Massive Scale: Cursors can handle result sets up to 50 million records, vastly exceeding standard SOQL limits.
  • Stateless Resumability: You can store a CursorId and a position, allowing a different transaction (such as a later Queueable or a separate API call) to resume processing from the exact same point.
  • Consistent UI Pagination: The new PaginationCursor class ensures that if records are deleted while a user is paging through a list, the page size and offsets remain consistent.

Code Implementation: Fetching Data in Batches

Implementing a cursor is straightforward. Here is a pattern for processing a large volume of contacts using the new Database.Cursor class:

// Create a cursor for high-volume processing
Database.Cursor cursor = Database.getCursor(
    'SELECT Id, Name, Email FROM Contact WHERE CreatedDate = THIS_YEAR'
);

// Process records in batches of 200
while (cursor.hasNext()) {
    List<Contact> batch = cursor.fetch(200);
    for (Contact c : batch) {
        System.debug('Processing: ' + c.Name);
    }
}

// Save position for potential resumption in another transaction
String cursorId = cursor.getCursorId();
Integer lastPosition = cursor.getPosition();

Apex Cursors vs. Batch Apex

While Batch Apex remains useful for standard asynchronous processing, Cursors offer distinct advantages for Architects:

FeatureBatch ApexApex Cursors
Record Limit50 Million50 Million
FlexibilityRigid structure (Start, Execute, Finish)Highly flexible; can be used in Queueables, REST, etc.
ConsistencySnapshot-basedCached results; PaginationCursor handles deletions
OverheadHigh (Job queuing/tracking)Low (On-demand fetching)

Architectural Governance and Limits

To ensure platform stability, Salesforce has implemented specific limits for Cursors in the Spring ’26 release:

  • Instance Limit: 10,000 cursor instances per 24-hour period per org.
  • Result Set Size: 50 million records for standard cursors; 100,000 for PaginationCursors.
  • Timeout: Cursors are cached for a limited window; long-term storage of cursor IDs should be avoided.

By adopting Apex Cursors, technical architects can now design more responsive, scalable, and memory-efficient data integration and processing layers that were previously impossible without complex external middleware.