Database.Stateful batch holds no instance state

ID

apex.performance.database_stateful_unneeded

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Performance

Language

Apex

Description

Reports a batch class implementing Database.Stateful that declares no instance field - only methods, or static members.

Rationale

Database.Stateful exists to carry values from one chunk of a batch to the next, and the platform pays for it by serializing the instance after every chunk and deserializing it before the next one. A class with nothing but methods and static members has nothing to carry: static members are reset between chunks whether the interface is there or not, so the serialization round trip runs on an empty object for the whole job. The interface also tells the next reader that the class accumulates something, which sends them looking for state that is not there.

The following code illustrates the pattern detected by this rule:

// FLAGGED: Database.Stateful batch holds no instance state
global class ContactTouchBatch implements Database.Batchable<SObject>, Database.Stateful {
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT Id FROM Contact');
    }
    global void execute(Database.BatchableContext bc, List<SObject> scope) {
        update scope;
    }
    global void finish(Database.BatchableContext bc) {
        System.debug('done');
    }
}

Remediation

Drop Database.Stateful from the implements list. Where the job really does need to accumulate - a running total, a list of failed ids - declare it as an instance field, because a static one does not survive the chunk boundary and will silently read as its initial value in finish.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved