In Spring Batch, what is the difference between a JobInstance and a JobExecution?
answer
- Instance = logical run; Execution = one attempt
- Identity = job name + identifying params
- One instance -> many executions (restart)
- BATCH_JOB_INSTANCE vs BATCH_JOB_EXECUTION
- Completed instance -> AlreadyCompleteException
basics
~20 sA JobInstance is a logical run of a job (job name + its identifying parameters). A JobExecution is a single attempt to run that instance. One JobInstance can have several JobExecutions if earlier attempts failed and were restarted.
solid answer
~40 sA JobInstance represents the logical concept of a job run — it is identified by the job's name plus its identifying JobParameters (for example an 'end-of-day' job for date 2026-07-22). A JobExecution is one concrete attempt to run that JobInstance: it has a start time, end time, BatchStatus (STARTED, COMPLETED, FAILED) and ExitStatus. The relationship is one-to-many: a single JobInstance can own many JobExecutions. If the first attempt fails, restarting the same instance creates a second JobExecution against the same JobInstance, so the instance is 'run number N' while each execution is 'attempt M of that run'. Spring Batch persists both in its metadata tables (BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION) via the JobRepository.
code
java · 15 lines// A JobExecution is what JobLauncher.run(...) returns.
// From it you can walk back to the owning JobInstance.
JobExecution execution = jobLauncher.run(endOfDayJob,
new JobParametersBuilder()
.addLocalDate("runDate", LocalDate.of(2026, 7, 22))
.toJobParameters());
JobInstance instance = execution.getJobInstance();
System.out.println(instance.getJobName()); // "endOfDayJob"
System.out.println(instance.getInstanceId()); // logical run id (BATCH_JOB_INSTANCE)
System.out.println(execution.getId()); // this attempt's id (BATCH_JOB_EXECUTION)
System.out.println(execution.getStatus()); // BatchStatus, e.g. COMPLETED or FAILED
// If this attempt failed and we relaunch with the SAME runDate,
// Spring Batch reuses `instance` and creates a NEW JobExecution.go deeper
Must nail the one-line distinction: instance = logical run, execution = one attempt, one-to-many on restart.
Should name the metadata tables and know restart reuses the instance and adds an execution.
Should connect the distinction to restartability, ExecutionContext reuse, and the JobRepository/JobLauncher flow.
Should reason about identity as the contract that makes idempotency and audit possible, and its operational consequences.
## The two core domain objects Spring Batch models a batch job with a small set of domain objects. The two most fundamental are **`JobInstance`** and **`JobExecution`**, and confusing them is the single most common Spring Batch mistake. ### JobInstance = a logical run A **`JobInstance`** represents the *logical* notion of 'this job, run for this input'. It is uniquely identified by: 1. the **job name** (the `Job` bean's name), and 2. the **identifying `JobParameters`** for that run. Example: an end-of-day settlement job that runs once per business day. The run for `2026-07-21` and the run for `2026-07-22` are **two different `JobInstance`s**, because their identifying parameter (the date) differs. Think of a `JobInstance` as answering *'which run is this?'*. It is stored in the **`BATCH_JOB_INSTANCE`** table. > Note: *which* parameters count toward identity (identifying vs non-identifying `JobParameters`) is governed by a separate mechanism covered elsewhere. Here it is enough to know that identity = job name + identifying parameters. ### JobExecution = one attempt A **`JobExecution`** represents a *single attempt* to run a `JobInstance`. It carries the runtime state of that attempt: - **`BatchStatus`** — an enum: `STARTING`, `STARTED`, `STOPPING`, `STOPPED`, `FAILED`, `COMPLETED`, `ABANDONED`. - **`ExitStatus`** — a richer exit code (e.g. `COMPLETED`, `FAILED`, or a custom string) usable for flow decisions. - `startTime`, `endTime`, `createTime`, `lastUpdated`. - A list of **`StepExecution`s** (one per step attempt). - An **`ExecutionContext`** (key/value state persisted for restart). - A reference back to its `JobInstance`. It is stored in the **`BATCH_JOB_EXECUTION`** table, with a foreign key to `BATCH_JOB_INSTANCE`. ### The one-to-many relationship One `JobInstance` can have **many** `JobExecution`s. This happens on **restart**: 1. You launch the end-of-day job for `2026-07-22`. A `JobInstance` is created, and a first `JobExecution` starts. 2. It **fails** halfway (DB outage). That `JobExecution` ends with `BatchStatus.FAILED`. 3. You relaunch with the **same** identifying parameters. Spring Batch finds the **existing** `JobInstance` (identity matches) and creates a **new, second** `JobExecution` to retry — reusing the persisted `ExecutionContext` so restartable steps can resume. So: `JobInstance` = 'the run', `JobExecution` = 'attempt #N of the run'. ### Why the distinction matters - **Restartability**: Spring Batch can only resume a run if it can identify the same `JobInstance` and find its prior failed `JobExecution` and saved context. - **Preventing duplicate work**: if a `JobInstance` already `COMPLETED`, relaunching it with identical identifying parameters throws **`JobInstanceAlreadyCompleteException`** — you cannot silently re-run yesterday's completed settlement. - **Auditing**: the metadata tables give you a full history — every attempt (`JobExecution`) grouped under its logical run (`JobInstance`). ### Who creates them The **`JobRepository`** persists both. The **`JobLauncher`** (via `run(Job, JobParameters)`) asks the repository for the matching `JobInstance` (creating one if none exists), then creates a fresh `JobExecution`, and runs it. ### Common gotchas - Relaunching with the *exact same* identifying parameters does **not** create a new `JobInstance` — it targets the existing one (and may throw if it already completed). To get a brand-new run, an **identifying parameter must change** (a common trick is a `RunIdIncrementer` or a timestamp). - `StepExecution` belongs to a `JobExecution`, not directly to a `JobInstance`. - `BatchStatus` (framework enum) and `ExitStatus` (flow-control code) are different things and live on the `JobExecution`/`StepExecution`.
- If a job's first execution fails and you restart it, how many JobInstances and JobExecutions exist?One JobInstance (identity unchanged) and two JobExecutions — the failed attempt and the restart attempt, both linked to that single instance.
- Which object holds the BatchStatus and StepExecutions — JobInstance or JobExecution?JobExecution. The JobInstance is just the logical identity; runtime status, timing, StepExecutions and the ExecutionContext all live on the JobExecution.
saying these in an interview costs you the question
- Saying JobInstance and JobExecution are the same thing or interchangeable
- Claiming each restart creates a new JobInstance
- Putting BatchStatus/StepExecutions on the JobInstance instead of the JobExecution