- SalesforceChaCha
- Posts
- 💃 A game-changer coming to Apex 🕺
💃 A game-changer coming to Apex 🕺
We're stoked about this Salesforce '24 Release feature
Good morning, Salesforce Nerds!
There’s a new toy coming soon for Salesforce Developers that need to process large datasets! 🥳
I don’t know about you, but I’m excited to get my hands on it and try it out.
As part of the Summer ‘24 release, Salesforce is releasing a Beta version of Apex Cursors!
Giving architects & developers a great alternative to Batch Apex! 🤙

DevOps Summit: Developing a long-term Salesforce DevOps mindset
Register now for the Virtual DevOps Summit

This year at the DevOps Summit, get your workload under control with DevOps best practices. You’ll hear real-world insights about the DevOps strategies and tooling that can accelerate your delivery, and drive sustainable growth for your organisation.
Listen to experts, Jonny Harris (Zurich) and Sami Hawkins (West Shore Home) as they share insights into how their teams leveraged DevOps best practices to meet growing demand.
If you’re looking for scalable ways to develop on Salesforce, join us.
TABLE OF CONTENTS
Peep this Summer '24 Apex Beta Feature
DRUM ROLL PLEASE
INTRODUCING APEX CURSORS
Apex cursors let you break up the processing of a SOQL query result into smaller pieces. 🧩
These separate pieces can then be processed within the bounds of a single transaction.
These give you with the ability to work with large query result sets, without actually returning the entire result set. 🔥
With cursors you can:
✅ Traverse a query result in parts
✅ Navigate both forward and backward in the result set
If you work with high-volume and high-resource processing jobs - these bad boys can help you out!
What’s cool is that these are a great alternative to batch Apex. They even address some of batch Apex’s limitations.
Cursors are also super powerful because they can be used in a chain of queueable Apex jobs. ⛓️
WHAT’S THE BIG DEAL
HOW DO THEY HELP?
In a word?
Performance! 🚀
An Apex cursor will boost performance by let you process query results in increments.
So, instead of getting all the records you just get a subset. Do your thing. Then move on to the next subset you need to work with. 🔥
This gives you some benefits:
✅ Memory management - don’t load the entire dataset. It strains the system. Get a smaller piece of it to work with.
✅ Navigation - you can move forward AND backward through the returned dataset. Super flexible.
✅ Transactions - a cursor operates within the bounds of a single transaction.
WHAT’S NEXT
ALL THE THINGS!
To use an Apex cursor here’s what you’ll need to do:
👉️ Create the cursor - run a SOQL query with Database.getCursor()
or Database.getCursorWithBinds()
and a cursor will be spawned representing the dataset.
👉️ Fetch records from the cursor - use the fetch()
method to get a specified number of records from a the cursor. It takes two integers as arguments - a position within the cursor to start returning data and a count for how many rows to return.
As with anything Salesforce there are limits. Let’s check them out:
❌ Max # of rows per cursor: 50 million (both synchronous and asynchronous)
❌ Max # of fetch calls per transaction: 10 (both synchronous and asynchronous)
❌ Max # of cursors per day: 10,000 (both synchronous and asynchronous)
❌ Max # of rows per day (aggregate limit): 100 million
EXAMPLE TIME
SHOW ME THE CODE!
public class QueryChunkingQueuable implements Queueable {
private Database.Cursor locator;
private integer position;
public QueryChunkingQueuable() {
locator = Database.getCursor
('SELECT Id FROM Contact WHERE LastActivityDate = LAST_N_DAYS:400');
position = 0;
}
public void execute(QueueableContext ctx) {
List<Contact> scope = locator.fetch(position, 200);
position += scope.size();
// PROCESS THE DATA HERE
if(position < locator.getNumRecords() ) {
// process the next chunk
System.enqueueJob(this);
}
}
}
Here we instantiate a Cursor
by executing a SOQL statement that will return the Id’s of each Contact
with the LastActivityDate
within the past 400 days.
Then when we’re in the execute()
method we just fetch the next 200 rows from the cursor.
Run our undoubtedly superb business logic.
Since we’re keeping track of the position
, we can check if there are more rows in need processing. If so, queue the job up.
SOUL FOOD
Today’s Principle
"The best preparation for tomorrow is doing your best today.”
and now....Salesforce Memes



What did you think about today's newsletter? |