# 3. Chunk-oriented processing: what "chunk(10)" actually does [← Previous](02-anatomy-of-a-job.md) | [README](../README.md) | [Next: The item processor as a filter →](04-item-processor-as-filter.md) `chunk(10)` means: read up to 10 items (calling the reader once per item), run each through the processor, then hand all the survivors to the writer in **one call**, inside **one transaction**. If the writer succeeds, the transaction commits and the step's counters — read, write, filter, commit — move forward together. If anything in that chunk throws, the whole transaction rolls back: none of those 10 items' writes are kept, even the ones that would have succeeded on their own. The happy-path run of this module's `productImportJob` against clean data makes this concrete. 60 rows, chunk size 10, two rows fail the processor's validation (filtered, not written): ```console $ SELECT read_count, filter_count, write_count, commit_count FROM BATCH_STEP_EXECUTION; READ_COUNT | FILTER_COUNT | WRITE_COUNT | COMMIT_COUNT 60 | 2 | 58 | 6 ``` Full transcript: [`docs/output/05-happy-path.txt`](output/05-happy-path.txt), source: [`ProductValidatingProcessor.java`](../src/main/java/com/ankurm/batch/processing/ProductValidatingProcessor.java). 60 rows at chunk size 10 is 6 chunks — `COMMIT_COUNT` confirms all 6 committed, one transaction each.
60 rows → six chunks of 10, each its own transaction 1-10 11-20 21-30 31-40 41-50 51-60 Each box: read 10 → process 10 (0-1 filtered) → write survivors → COMMIT. Row 12 (chunk 2) and row 33 (chunk 4) are filtered by the processor -- see chapter 4 -- so those two chunks commit 9 rows instead of 10. 58 rows land in PRODUCT; every chunk still commits.
## Why 10, and what changes if you pick a different size Chunk size is a trade-off with no universally right answer: - **Smaller chunks** commit more often, so a failure loses less work and transactions are shorter (less lock contention, smaller rollback). They also mean more round trips to the database — more commit overhead per row. - **Larger chunks** amortize that overhead across more rows, but a failure anywhere in the chunk costs you the whole chunk's work, and the transaction held open is bigger and longer. 10 is small enough that chapter 7's poisoned row costs you 12 rows of rework at most (one chunk), not thousands, and small enough to demonstrate multiple commits from 60 rows without a huge fixture file. Production jobs processing millions of rows commonly use chunk sizes in the hundreds or low thousands; the right number depends on row size, write cost, and how expensive a partial redo is for your specific job — there is no formula that replaces measuring it against your own writer. ## Going deeper - The chunk-processing reference: [Spring Batch — Chunk-oriented processing](https://docs.spring.io/spring-batch/reference/step/chunk-oriented-processing.html) (`rel="nofollow"`). - `ChunkOrientedStep` itself, if you want to see the commit/rollback logic this chapter describes: `org.springframework.batch.core.step.item.ChunkOrientedStep` in `spring-batch-core-6.0.5.jar` (the stack trace in [`docs/output/07-restart-run1-fails.txt`](output/07-restart-run1-fails.txt) names it directly). - What happens when the processor itself decides to drop a row rather than the writer failing: [chapter 4](04-item-processor-as-filter.md). [Next: The item processor as a filter →](04-item-processor-as-filter.md)