Kubernetes
Spring Batch
Scalable Jobs
Cloud Computing
Container Orchestration

Scalable spring batch job on kubernetes

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Spring Batch can scale on Kubernetes, but only if you align the batch model with Kubernetes job semantics. The common mistake is to deploy a batch application like a long-running web service and then call extra replicas "scaling." Real scalability comes from partitioning work and coordinating it through a shared job repository.

Use a Kubernetes Job, Not a Deployment

Batch workloads are finite by nature:

  • start
  • process data
  • finish

That maps naturally to a Kubernetes Job, not a Deployment.

Minimal example:

yaml
1apiVersion: batch/v1
2kind: Job
3metadata:
4  name: spring-batch-import
5spec:
6  template:
7    spec:
8      restartPolicy: Never
9      containers:
10        - name: app
11          image: my-registry/spring-batch-app:latest
12          args: ["--spring.batch.job.name=importJob"]

Using a Deployment for one-off batch work usually creates awkward behavior around retries, completion, and replica management. A Job gives Kubernetes the correct lifecycle model from the beginning.

The Job Repository Must Be Shared

Spring Batch tracks execution state, step progress, failures, and restart metadata through its job repository. If you want multiple Pods or workers to cooperate, they need a shared durable repository, typically backed by an external database.

Without that, scaling is unreliable because each container loses sight of what the others already did.

So the architecture usually includes:

  • containerized Spring Batch app
  • shared job repository database
  • Kubernetes Job or CronJob launcher
  • partitioning or remote chunking strategy

That repository is part of correctness, not just observability.

Horizontal Scaling Requires Work Partitioning

Running four identical Pods against the same batch step does not magically parallelize Spring Batch safely. You need a deliberate split of work:

  • partitioned steps
  • remote chunking
  • or separate job parameters that assign non-overlapping data slices

A partitioned step in Spring Batch might look like this:

java
1@Bean
2public Step masterStep(JobRepository jobRepository, Step workerStep, TaskExecutor taskExecutor) {
3    return new StepBuilder("masterStep", jobRepository)
4        .partitioner("workerStep", partitioner())
5        .step(workerStep)
6        .gridSize(4)
7        .taskExecutor(taskExecutor)
8        .build();
9}

The important idea is that each worker receives a defined slice of the total workload. Without that, extra Pods only create duplicate processing or lock contention.

Kubernetes Adds Elastic Compute, Not Batch Semantics

Kubernetes is excellent at:

  • launching workers
  • isolating resources
  • retrying failed Pods
  • scaling compute pools

Spring Batch is excellent at:

  • step control
  • restartability
  • chunk processing
  • execution state

Treat them as complementary. Kubernetes should not replace the job repository, and Spring Batch should not pretend to be an orchestrator by itself.

Think About Restartability and Idempotency

A scalable batch system must assume retries happen:

  • Pods can be evicted
  • nodes can fail
  • jobs can be re-run

That means workers should be restartable and, where possible, idempotent. If a Pod dies halfway through a partition, the system should be able to retry that slice without corrupting the data or duplicating irreversible side effects.

This is where many "scaled" batch systems fail. They increase throughput but lose operational safety.

Tune at the Step Level, Not Just the Pod Count

Performance depends on more than replica count. Spring Batch throughput still depends on:

  • chunk size
  • reader and writer efficiency
  • transaction boundaries
  • partition size
  • database throughput
  • memory per worker

A sensible tuning process is:

  1. make one worker correct
  2. measure bottlenecks
  3. add partitioning
  4. increase worker count gradually

Blindly scaling Pods before step design is stable usually just multiplies database or I/O contention.

CronJobs for Scheduled Batch Runs

If the batch run is periodic, wrap the same container in a Kubernetes CronJob:

yaml
1apiVersion: batch/v1
2kind: CronJob
3metadata:
4  name: nightly-import
5spec:
6  schedule: "0 2 * * *"
7  jobTemplate:
8    spec:
9      template:
10        spec:
11          restartPolicy: Never
12          containers:
13            - name: app
14              image: my-registry/spring-batch-app:latest

This gives you Kubernetes-native scheduling while still keeping Spring Batch responsible for execution semantics inside the container.

Observability Matters Once You Scale

After the workload spans multiple Pods, you need visibility into:

  • job and step duration
  • partition success and retry counts
  • Pod failures
  • queue or backlog size
  • database pressure from the job repository

Without these signals, a "scalable" design can degrade quietly and be harder to operate than a single-node job.

Common Pitfalls

  • Deploying Spring Batch as a Deployment and treating replica count as true batch scaling.
  • Running multiple Pods without partitioning or another clear split of work.
  • Forgetting that all workers need a shared durable job repository.
  • Increasing Pod count before understanding database and I/O bottlenecks.
  • Ignoring restart and idempotency requirements while focusing only on throughput.

Summary

  • Scalable Spring Batch on Kubernetes starts with the right primitive: Job or CronJob, not Deployment.
  • Real horizontal scale requires partitioning, remote chunking, or another deliberate work-splitting strategy.
  • A shared job repository is essential for correctness and restartability.
  • Kubernetes provides elastic execution, while Spring Batch provides batch semantics.
  • Throughput only matters if the system stays restartable, observable, and partition-safe.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.