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

Spring Batch writers: use a stable source key when a chunk is replayed

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

A restart can encounter a previously committed item; a stable business key lets the destination detect or reconcile that replay.

Download Spring source kit

Make the replay decision visible

The H2 fixture keys receipt_import by source ID. A plain INSERT exposed a duplicate-key failure on restart even though the first chunk had committed. The checked writer uses H2 MERGE keyed by ID. After restart, the table has four rows: ID 1 retains seven units and ID 4 has 28. This MERGE syntax is H2-specific. A production ledger should also reject a reused source ID whose payload changed, rather than silently overwriting it.

Keep writer state separate from metadata

The failed execution's saved reader context reports two reads, yet the local restart can revisit earlier rows. Even with another reader implementation, a crash between business and repository commits can make replay possible. Keep the sink key stable and the operation idempotent. An external broker send is a separate side effect; the outbox records intent inside the business transaction.

Checked excerpt

Java
jdbc.update("MERGE INTO receipt_import (id, units) KEY (id) VALUES (?, ?)",
    receipt.id(), receipt.units());

Cost and verification

The unique key adds indexed lookup work per row. An upsert may write an existing row again; compare content or version before accepting a changed replay. The isolated source-kit project checks the stated local behavior.

Common Mistakes

  • Do not silently overwrite a changed source record under the same ID.
  • Do not confuse a saved reader count with exactly-once output.
  • Do not copy H2 MERGE syntax into another database without checking semantics.

Read next

Spring Batch chunks: a later failure does not erase an earlier commit, Spring Batch job identity: a manifest ID defines restart versus a new run, Spring transactional outbox: commit a receipt and event row together, Spring POST idempotency keys: bind replay to tenant and command.

Related Spring path

Continue with Spring Batch reconciliation: report accepted and rejected receipt IDs.

spring
spring-boot
spring-batch
batch-idempotent-writer
Storage details