{"id":13128,"date":"2026-08-18T06:24:08","date_gmt":"2026-08-18T06:24:08","guid":{"rendered":"https:\/\/www.greytrix.com\/blogs\/salesforce\/?p=13128"},"modified":"2026-08-18T06:24:10","modified_gmt":"2026-08-18T06:24:10","slug":"apex-cursors-vs-batch-apex-which-salesforce-data-processing-approach-should-you-use","status":"publish","type":"post","link":"https:\/\/www.greytrix.com\/blogs\/salesforce\/2026\/08\/18\/apex-cursors-vs-batch-apex-which-salesforce-data-processing-approach-should-you-use\/","title":{"rendered":"Apex Cursors vs. Batch Apex: Which Salesforce Data Processing Approach Should You Use?"},"content":{"rendered":"\n<p>Processing large volumes of records is a common requirement in Salesforce. Traditionally, Batch Apex has been the preferred approach for processing large datasets asynchronously.<\/p>\n\n\n\n<p>With the introduction of Apex Cursors, developers now have another option for working with large SOQL result sets. Apex Cursors became generally available in Spring \u201926 (API version 66.0) and provide more control over how records are retrieved and processed.<\/p>\n\n\n\n<p>But does this mean Apex Cursors replace Batch Apex?<\/p>\n\n\n\n<p>No. Both have different purposes and should be selected based on the requirement.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">What is Batch Apex?<\/mark><\/strong><\/h2>\n\n\n\n<p>Batch Apex is an asynchronous framework that allows Salesforce developers to process large numbers of records in smaller groups.<\/p>\n\n\n\n<p>A Batch Apex class contains three main methods:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>start()<\/strong> \u2013 identifies the records.<\/li>\n\n\n\n<li><strong>execute()<\/strong> \u2013 processes each batch.<\/li>\n\n\n\n<li><strong>finish()<\/strong> \u2013 performs post-processing.<\/li>\n<\/ul>\n\n\n\n<p>If there are thousands of records, Salesforce processes them in multiple transactions.<\/p>\n\n\n\n<p>Records <br>   \u2193<br>Batch Apex <br>   \u2193 <br>200 \u2192 Execute <br>200 \u2192 Execute <br>200 \u2192 Execute <br>   \u2193 <br>Completed<\/p>\n\n\n\n<p>A major advantage is that each execute() runs in a separate transaction, so governor limits are reset for each batch.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">What are Apex Cursors?<\/mark><\/strong><\/h2>\n\n\n\n<p>Apex Cursors allow developers to work with large SOQL result sets by retrieving records in smaller chunks.<\/p>\n\n\n\n<p>Unlike Batch Apex, the developer controls the position and number of records retrieved.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><a><\/a><strong>Example<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Database.Cursor cursor = Database.getCursor(\n'SELECT Id, Name FROM Account ORDER BY Id'\n);<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Integer totalRecords = cursor.getNumRecords();\nInteger position = 0;\nInteger chunkSize = 200;\n\nwhile (position &lt; totalRecords) {\n    Integer fetchSize = Math.min(\n        chunkSize,\n        totalRecords - position\n    );\n    \nList&lt;Account> accounts =\n        cursor.fetch(position, fetchSize);\n \n    for (Account acc : accounts) {\n        System.debug(acc.Name);\n    }\n \n    position += accounts.size();\n}\n<\/code><\/pre>\n\n\n\n<p>The records are retrieved progressively:<br><br>Cursor<br>   \u2193<br>fetch(0, 200)<br>   \u2193<br>fetch(200, 200)<br> \u00a0 \u2193<br>fetch(400, 200)<br> \u00a0 \u2193<br>Continue&#8230;<\/p>\n\n\n\n<p>This provides greater control over how the result set is processed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">Apex Cursors vs Batch Apex<\/mark><\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Feature<\/strong><\/td><td><strong>Batch Apex<\/strong><\/td><td><strong>Apex Cursors<\/strong><\/td><\/tr><tr><td>Primary purpose<\/td><td>Large-scale processing<\/td><td>Large result-set retrieval<\/td><\/tr><tr><td>Processing control<\/td><td>Salesforce-managed<\/td><td>Developer-controlled<\/td><\/tr><tr><td>Chunk size<\/td><td>Batch size<\/td><td>fetch() size<\/td><\/tr><tr><td>Separate transactions<\/td><td>Yes<\/td><td>No<\/td><\/tr><tr><td>Governor limits reset<\/td><td>Yes<\/td><td>No<\/td><\/tr><tr><td>Large datasets<\/td><td>Excellent<\/td><td>Excellent<\/td><\/tr><tr><td>DML processing<\/td><td>Excellent<\/td><td>Possible<\/td><\/tr><tr><td>Queueable integration<\/td><td>Possible<\/td><td>Useful<\/td><\/tr><tr><td>Best for<\/td><td>Bulk processing<\/td><td>Flexible processing<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">Governor Limits<\/mark><\/strong><\/h2>\n\n\n\n<p>One of the biggest differences is transaction handling.<\/p>\n\n\n\n<p>With Batch Apex:<\/p>\n\n\n\n<p>Batch 1 \u2192 Transaction 1 \u2192 Limits <br>Batch 2 \u2192 Transaction 2 \u2192 Limits Reset <br>Batch 3 \u2192 Transaction 3 \u2192 Limits Reset<\/p>\n\n\n\n<p>With Apex Cursors, calling fetch() does not automatically create a new transaction.<\/p>\n\n\n\n<p>Therefore, Apex Cursors do not bypass governor limits. They mainly provide controlled access to a large query result set.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">When Should You Use Batch Apex?<\/mark><\/strong><\/h2>\n\n\n\n<p>Choose Batch Apex when:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>You need a large-scale DML.<\/li>\n\n\n\n<li>You need separate transactions.<\/li>\n\n\n\n<li>You need governor limits to reset between batches.<\/li>\n\n\n\n<li>You need scheduled or background processing.<\/li>\n\n\n\n<li>Records can be processed independently.<\/li>\n<\/ul>\n\n\n\n<p><strong>Examples:<\/strong> Data cleanup, mass updates, data migration, and scheduled synchronization.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">When Should You Use Apex Cursors?<\/mark><\/strong><\/h2>\n\n\n\n<p>Consider Apex Cursors when:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>You need to process a large SOQL result set.<\/li>\n\n\n\n<li>You need control over the fetch size.<\/li>\n\n\n\n<li>You need control over the position of retrieved records.<\/li>\n\n\n\n<li>You are building a custom processing solution.<\/li>\n\n\n\n<li>You want to combine cursor processing with Queueable Apex.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">Conclusion<\/mark><\/strong><\/h2>\n\n\n\n<p>Apex Cursors do not replace Batch Apex. Instead, they provide Salesforce developers with another option for handling large datasets.<\/p>\n\n\n\n<p>Batch Apex is ideal when you need Salesforce-managed asynchronous processing with separate transactions.<\/p>\n\n\n\n<p>Apex Cursors are useful when you need more control over how a large SOQL result set is retrieved and processed.<\/p>\n\n\n\n<p>The key is to choose the approach based on the requirement rather than simply choosing the newer feature.<\/p>\n\n\n\n<p>By following the above blog instructions, you will be able to learn \u201c<strong>Apex Cursors vs. Batch Apex: Which Salesforce Data Processing Approach Should You Use?<\/strong>\u201c. If you still have queries or any related problems, don\u2019t hesitate to contact us at <a href=\"mailto:salesforce@greytrix.com\" target=\"_blank\" rel=\"noreferrer noopener\">salesforce@greytrix.com<\/a>. More details about our integration product are available on <a href=\"https:\/\/www.greytrix.com\/salesforce-cloud-services\/\" target=\"_blank\" rel=\"noreferrer noopener\">our website<\/a> and <a href=\"https:\/\/appexchange.salesforce.com\/appxListingDetail?listingId=a0N30000000psM5EAI\" target=\"_blank\" rel=\"noreferrer noopener\">Salesforce AppExchange<\/a>.<\/p>\n\n\n\n<p>We hope you may find this blog resourceful and helpful. However, if you still have concerns and need more help, please contact us at <a href=\"mailto:salesforce@greytrix.com\" target=\"_blank\" rel=\"noreferrer noopener\">salesforce@greytrix.com<\/a>.<\/p>\n\n\n\n<p style=\"text-align: justify\"><b>About Us<\/b><\/br>\n<p><a href=\"https:\/\/www.greytrix.com\/\">Greytrix<\/a> \u2013 a globally recognized and one of the oldest Sage Development Partner and a Salesforce Product development partner offers a wide variety of integration products and services to the end users as well as to the Partners and Sage PSG across the globe. We offer Consultation, Configuration, Training and support services in out-of-the-box functionality as well as customizations to incorporate custom business rules and functionalities that require apex code incorporation into the Salesforce platform.<br><br> Greytrix has some unique solutions for Cloud CRM such as <a href=\"\">Salesforce Sage integration<\/a> for <a href=\"https:\/\/www.greytrix.com\/sage-x3-erp\/integration\/\">Sage X3<\/a>, <a href=\"https:\/\/www.greytrix.com\/salesforce-cloud-services\/sage-100-integration\/\">Sage 100<\/a> and <a href=\"https:\/\/www.greytrix.com\/salesforce-cloud-services\/sage-300-integration\/\">Sage 300 (Sage Accpac)<\/a>. We also offer best-in-class Cloud CRM <a href=\"https:\/\/www.greytrix.com\/salesforce-cloud-services\/crm-development\/\">Salesforce customization and development services<\/a> along with services such as Salesforce <a href=\"https:\/\/www.greytrix.com\/salesforce-cloud-services\/data-migration-support\/\">Data Migration<\/a>, <a href=\"https:\/\/www.greytrix.com\/salesforce-cloud-services\/crm-development\/\">Integrated App development<\/a>, Custom App development and Technical Support business partners and end users. Salesforce Cloud CRM integration offered by Greytrix works with Lightning web components and supports standard opportunity workflow. Greytrix GUMU&#x2122; integration for Sage ERP \u2013 Salesforce is a 5-star rated app listed on <a href=\"https:\/\/appexchange.salesforce.com\/appxListingDetail?listingId=a0N30000000psM5EAI\" target=\"_blank\" rel=\"noopener\">Salesforce AppExchange<\/a>.<br> The GUMU&#x2122; Cloud framework by Greytrix forms the backbone of cloud integrations that are managed in real-time for processing and execution of application programs at the click of a button.<br><br> For more information on our Salesforce products and services, contact us at <a href=\"mailto:salesforce@greytrix.com\">salesforce@greytrix.com<\/a>. We will be glad to assist you.<\/p>\n\n\n\n<p><strong>Related Posts:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.greytrix.com\/blogs\/salesforce\/tag\/asynchronousprocessing\/\" target=\"_blank\" rel=\"noreferrer noopener\">How to Avoid Recursive Batch Execution in Salesforce Apex<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.greytrix.com\/blogs\/salesforce\/tag\/apex-asynchronous-processing\/\" target=\"_blank\" rel=\"noreferrer noopener\">Smart Ways to Debug Salesforce Flows with Asynchronous Apex methods<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.greytrix.com\/blogs\/salesforce\/tag\/batch-apex\/\" target=\"_blank\" rel=\"noreferrer noopener\">Batch Processing in Salesforce<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Processing large volumes of records is a common requirement in Salesforce. Traditionally, Batch Apex has been the preferred approach for processing large datasets asynchronously. With the introduction of Apex Cursors, developers now have another option for working with large SOQL result sets. Apex Cursors became generally available in Spring \u201926 (API version 66.0) and provide\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.greytrix.com\/blogs\/salesforce\/2026\/08\/18\/apex-cursors-vs-batch-apex-which-salesforce-data-processing-approach-should-you-use\/\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[3627,2318,3541,3554,3555,3255,3548,3549,2160,31,3550,3542,3545,3547,3553,3552,3543,2158,367,2467,588,3418,1709,3532,2463,2048,3083,392,2782,3421,397,2567,3544,3512,3546,3417,3551],"class_list":["post-13128","post","type-post","status-publish","format-standard","hentry","category-salesforce-srv","tag-apex-best-practices-2","tag-apex-best-practices","tag-apex-bulkification","tag-apex-collections","tag-apex-maps","tag-apex-programming","tag-apex-trigger-best-practices","tag-apex-trigger-optimization","tag-asynchronous-apex","tag-batch-apex","tag-bulk-data-processing","tag-bulkification-in-apex","tag-bulkified-apex-code","tag-dml-best-practices","tag-dml-optimization","tag-future-methods","tag-governor-limit-safe-code","tag-queueable-apex","tag-salesforce","tag-salesforce-admin","tag-salesforce-apex","tag-salesforce-architecture","tag-salesforce-automation","tag-salesforce-code-optimization","tag-salesforce-coding-standards","tag-salesforce-crm","tag-salesforce-developer","tag-salesforce-development","tag-salesforce-development-best-practices","tag-salesforce-governor-limits","tag-salesforce-integration","tag-salesforce-performance","tag-salesforce-triggers","tag-salesforce-tutorial","tag-soql-best-practices","tag-soql-optimization","tag-trigger-framework"],"_links":{"self":[{"href":"https:\/\/www.greytrix.com\/blogs\/salesforce\/wp-json\/wp\/v2\/posts\/13128","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.greytrix.com\/blogs\/salesforce\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.greytrix.com\/blogs\/salesforce\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.greytrix.com\/blogs\/salesforce\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.greytrix.com\/blogs\/salesforce\/wp-json\/wp\/v2\/comments?post=13128"}],"version-history":[{"count":5,"href":"https:\/\/www.greytrix.com\/blogs\/salesforce\/wp-json\/wp\/v2\/posts\/13128\/revisions"}],"predecessor-version":[{"id":13133,"href":"https:\/\/www.greytrix.com\/blogs\/salesforce\/wp-json\/wp\/v2\/posts\/13128\/revisions\/13133"}],"wp:attachment":[{"href":"https:\/\/www.greytrix.com\/blogs\/salesforce\/wp-json\/wp\/v2\/media?parent=13128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.greytrix.com\/blogs\/salesforce\/wp-json\/wp\/v2\/categories?post=13128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.greytrix.com\/blogs\/salesforce\/wp-json\/wp\/v2\/tags?post=13128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}