Skip to content

BuildNot yet confirmed elsewhere1 publisher2 min readPublished

Spring's @Scheduled swallows the exception and reports success to the scheduler

A nightly job that catches its own failure and returns cleanly is invisible to every dashboard you can bolt on afterwards, which is why the durable execution argument lands on the event log rather than the feature list.

The Engineer · Build desk

How we use AISend a correction

Illustration accompanying Spring's @Scheduled swallows the exception and reports success to the scheduler
Generated illustration

What happened

  • A dev.to guide argues that Spring's @Scheduled breaks down at scale, then walks through migrating a production Spring Batch pipeline to Temporal with complete code examples.
  • The failure mode it names is a job that catches its exception, logs nothing meaningful, and returns success to the scheduler that launched it.
  • A second mode is overlap: the next cron trigger fires before the previous execution has finished, on jobs where nobody configured @ScheduledLock.
  • According to the guide, none of this appears in dashboards until a data audit flags inconsistencies in a critical report.
  • Temporal's pitch in the piece is that state transitions go to an event log, so a crashed process replays that log and resumes exactly where it stopped.

Why it matters

  • constraint Alerting built on scheduler outcomes cannot tell a swallowed exception from a clean run, so the detection gap survives every monitoring layer added above it.
  • exposure Teams that fix overlap with a lock library take on a new dependency whose own corruption nobody is watching, and it is the dependency holding back concurrent writes.
  • cost Adoption is paid in rewriting: the fault-tolerant chunk step becomes a workflow method calling separate read, process and write activities, not a configuration change.

Trace the call in the guide's own sample. `jobLauncher.run` throws, the catch block logs the exception, and the method returns normally [2]. The comment sitting in that catch block says what follows: no alert, no retry, no escalation [2]. To the scheduler, the invocation completed, which is the "returns success" the guide puts at the centre of the problem [1]. Anything layered above consumes the same signal. Teams bolt on Actuator, custom logging and Micrometer, and the guide's own verdict is that by the time there is real observability it is a custom framework to maintain [8]. A framework you did not plan to write is still a framework you keep patched.

The interval is what costs money. The sample runs on cron `0 0 2 * * *`, once a night, chunk size 500 [11]. The guide says data corruption from concurrent runs can take weeks to surface [17]. Take two weeks as the low end of that: one run a night for fourteen nights is fourteen executions writing against corrupted state before anyone reads the evidence [20].

Durable execution changes where the history lives. Temporal records every state transition to an event log, and a crashed process is recovered by replaying that log and resuming from the point it stopped [5][6]. The observability is a byproduct of the recovery mechanism: a log detailed enough to reconstruct an execution is detailed enough to answer which step ran and how it ended [15]. Compare that with `BATCH_JOB_INSTANCE` and `BATCH_JOB_EXECUTION`, which the guide notes you manage, prune and keep consistent yourself [10].

The requirement the guide leaves implicit sits in your code. If resuming means replaying recorded state transitions through the same plain Java methods, those methods have to reach the same points in the same order when they are re-executed [16]. That constraint decides whether a given job is a straightforward port or a redesign.

The piece carries no measured numbers, only a before/after diagram and code [13], so nothing here transfers as a benchmark; what transfers is the failure taxonomy, and only if your jobs have the same shape. The guide is straight about that: `@Scheduled` is fine for one or two simple jobs, and the debt accumulates by the time a team has dozens [19]. In my context, a dozen-plus jobs whose only witness is a log line, a queryable execution history is worth the port. At three jobs, the scheduler you already run plus a lock library is the cheaper answer, and the guide concedes that the lock approach works [9].

What to watch

  • Whether anyone publishes measured numbers for a migrated pipeline, since the guide argues from diagrams and code rather than metrics.
  • Whether Spring's scheduling stack ever ships a default execution history, which would take most of the observability argument off the table.
  • Whether migrating teams keep Spring Batch chunking inside activities or rewrite reader, processor and writer outright.

Clarity's read

What the record supports and how the coverage leans. The claims behind it follow.

Reality

Evidence38
Adoption
Insufficient
Hype gap+30
Incentives50
Confidence55
Why these scores

Claim ledger

Ranked by verification strength, evidence, and original report placement.

  1. [1]

    Scheduled jobs fail silently by catching exceptions, logging nothing meaningful, and returning success to the scheduler.

    ReportedSupportedSource: dev.to guide on Temporal vs Spring Batch2 sources— create a free account to open themView cited source
  2. [2]

    In the sample scheduler, jobLauncher.run is wrapped in a try/catch whose catch block logs "Invoice reconciliation failed" and carries the comment "No alert. No retry. No escalation."

    ReportedSupportedSource: dev.to guide code sample2 sources— create a free account to open themView cited source
  3. [3]

    In the guide's after-diagram, a Temporal scheduler triggers a workflow method that calls activities to read, process and write each chunk, with failures auto-retried, crashes replayed from the log and overlap prevented by a workflow ID lock.

    ReportedSupportedSource: dev.to guide architecture diagram2 sources— create a free account to open themView cited source

Sources

1 independent publisher whose own reporting we read for this story.

  1. dev.to

    1 article · August 27, 2026

    Temporal vs Spring Batch: Fixing Enterprise Java's Silent Job Failure Problem

Share your take

Let Clarity write the post for you.

Signed-in readers get a short post drafted on this story in the register they choose — narrative, analytical, or a direct position — editable to the last word before it goes anywhere. The share buttons at the top of this story work without an account.

Topics and entities

Follow any of these and your For You feed starts watching them — no settings page required.

Topics

Loading related stories