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

Spring Batch partitioner: assign disjoint receipt ranges

Last updated: 5 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

A partitioner assigns stable, named input ranges to worker StepExecutions; correctness starts with full coverage and no overlap.

Use half-open boundaries

A 47-row immutable manifest can be divided into four ranges: [0,12), [12,24), [24,36) and [36,47). Each worker owns its lower bound and excludes its upper bound. That convention avoids a duplicate row at a boundary and is easy to verify mechanically. The partitioner returns a distinct ExecutionContext for each named range; step-scoped components can bind to those values when a worker starts.

Name the work, not the thread

Give each partition a name derived from its immutable range or shard identity. Do not use a thread index, since scheduling order is not a business identity. A database query must filter by the exact partition predicate and a stable ordering key. If new rows can appear during the run, first freeze a source snapshot; otherwise a range calculated from changing row positions will miss or repeat work. Input snapshotting remains the first step.

Prove the partition set

Before launching workers, compare the union of assigned IDs with the manifest and assert every ID occurs once. After a forced partition failure, compare the destination set again. This is more useful than asserting only that the manager step completed: a manager can succeed while the partitioner silently omitted a range if the test input never exercises its edge.

Implementation contract

Java
int receiptCount = 47;
int targetPartitions = 4;
int width = (receiptCount + targetPartitions - 1) / targetPartitions;
Map<String, ExecutionContext> ranges = new LinkedHashMap<>();
for (int start = 0; start < receiptCount; start += width) {
    int endExclusive = Math.min(receiptCount, start + width);
    ExecutionContext input = new ExecutionContext();
    input.putInt("receipt.startInclusive", start);
    input.putInt("receipt.endExclusive", endExclusive);
    ranges.put("receiptRange-" + start, input);
}

Cost and verification

Partitioning adds worker setup and repository rows. It pays only when independent work exceeds coordination cost; database pool size and destination contention often cap throughput first.

Common Mistakes

  • Do not use inclusive upper bounds in adjacent ranges without adjusting the next lower bound.
  • Do not derive partition identity from the executing thread number.
  • Do not partition an unfrozen query result by row position.

Read next

Spring Batch partition restart: preserve worker names and input slices, Spring Batch restart input: pin the manifest before resuming a cursor, Spring Batch step scope: bind a reader to one execution, Spring Batch writers: use a stable source key when a chunk is replayed, Spring Batch job scope: avoid a shared bean in partition workers.

spring
spring-batch
batch-partition-range-ownership
Storage details