Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Batch chunk restart: know which receipts committed

Last updated: 1 Oct 20265 min read
tutorial
IntermediateBy AITrove Editorial

A Spring Batch chunk step reads, optionally transforms, and writes a bounded group of items within a transaction. Successful chunks commit independently, so a later failure does not roll back the entire import.

Place the restart cursor with the committed work

A receipt import with a chunk size of 100 may commit 200 rows and fail while writing the next group. Restart must resume according to the reader and JobRepository state, not simply begin from line one and hope duplicates are harmless. Choose a persistent repository when restart across process crashes matters. A resourceless repository cannot provide that durability.

Java
package in.aitrove.receipts;

import org.springframework.batch.core.step.Step;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.infrastructure.item.ItemReader;
import org.springframework.batch.infrastructure.item.ItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

record ImportedReceipt(long sourceId, long amountCents) {}

@Configuration
class ReceiptImportStep {
    @Bean
    Step receiptChunk(JobRepository repository,
                      PlatformTransactionManager transactions,
                      ItemReader<ImportedReceipt> reader,
                      ItemWriter<ImportedReceipt> writer) {
        return new StepBuilder("receiptChunk", repository)
            .<ImportedReceipt, ImportedReceipt>chunk(100)
            .transactionManager(transactions)
            .reader(reader)
            .writer(writer)
            .build();
    }
}

The example assumes reader and writer beans are configured separately and the Spring Batch dependency is installed. A chunk size is not a universal throughput knob. Larger chunks retain more items and hold transactions longer; smaller chunks increase commit and metadata work. Measure both against the database and input source.

Make duplicate writes rejectable

A file reader can replay a line after a crash if progress and destination writes are not coordinated as expected. Put a unique source identifier on each receipt and define whether a duplicate is skipped, reported or treated as a changed record. An external side effect inside a chunk is not rolled back by a database transaction.

Common Mistakes

  • Calling a job restartable without testing a process crash after a committed chunk.
  • Keeping an entire import in one transaction until the last line.
  • Using a non-durable repository for a job that must survive restarts.
  • Assuming a database rollback also retracts an already-sent message.

Read next

Receipt upload validation, atomic event records, and bounded backfills.

spring
spring-boot
batch-chunk-restart
Storage details