I've got to delete 5 million records and I'm trying to delete 900,000 records for each click, using batch Apex.

The code works in sandbox and worked in the production org last Thursday, but is now throwing an internal salesforce.com error when I try to run it.


public class deleteAllRecords implements Database.batchable<integer>, Iterator<integer>, iterable<integer> {
    integer counter = 0;
    public iterator<integer> iterator() {
        return this;
    public boolean hasnext() {
        return counter< 100;
    public integer next() {
            counter = 100;
        return counter++;
    public iterable<integer> start(database.batchablecontext context) {
        return this;
    public void execute(database.batchablecontext context, integer[] scope) {
        delete [select id from bad_records__c order by id limit 9000];
    public void finish(Database.batchablecontext context) {


I then execute anonymous -

Database.executeBatch(new deleteAllRecords(), 1);


SOQL_EXECUTE_BEGIN [25]|Aggregations:0|SELECT id FROM bad_records__c ORDER BY id ASC NULLS FIRST LIMIT 9000

FATAL_ERROR Internal Salesforce.com Error

Why did it work before, but now doesn't? Could this be something to do with a particular record?

Also, is this a sensible way to delete records in the first place? I have no truncate button on this object and committed the cardinal sin of copy pasting the above code from salesforce.stackexchange... as I understand it it just forces a new transaction for each 9000 record deletion block - is this a good idea?

Should I just manually run anonymous 500 times:

List<bad_records__c> deleteList = [select Id from bad_records__c limit 10000];
delete deleteList;

Or dataloader? Something else?

  • Anytime there is an internal error, it is Salesforce bug. You should file a ticket with them. They usually can identify the root cause even if it is related to your org data/code pattern. Also note that order by clause when you have lots of records in an object can be really slow. Considering you are trying to delete, not sure if ordering is necessary.
    – realfire
    Apr 17 '20 at 3:24

Not sure why it now fails. However, this seems a strange way to implement this sort of thing.

Given that a Batchable that returns a Database.QueryLocator is permitted to process 50 million records in the batch run, why not just do the following:

public class DeleteAllRecords implements Database.Batchable<SObject> {
    public Database.QueryLocator start(Database.BatchableContext context) {
        return [SELECT Id FROM Bad_Records__c];

    public void execute(Database.BatchableContext context, SObject[] scope) {
        delete scope;

    public void finish(Database.BatchableContext context) {

Depending on what processing you invoke when a Bad_Records__c instance is deleted, you can run this with a larger batch size.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.