How to monitor Spring @Scheduled tasks
To monitor Spring @Scheduled tasks, expose Spring Boot Actuator's GET /actuator/scheduledtasks endpoint to inspect each task's next and last execution times and status (STARTED, SUCCESS, or ERROR). For deeper observability, enable Spring's @EnableScheduling with Micrometer metrics so each task duration and error rate appears in your metrics backend. Add a heartbeat ping at the end of each important task so an external monitor can alert you when an expected execution doesn't happen.
How do I use the Actuator scheduledtasks endpoint?
Add the Actuator dependency and expose the scheduledtasks endpoint. It returns each task's schedule expression, last execution time, and status:
management:
endpoints:
web:
exposure:
include: health,scheduledtasks
endpoint:
scheduledtasks:
enabled: truecurl -s http://localhost:8080/actuator/scheduledtasks | python3 -m json.tool
# Returns: cron tasks, fixedRate tasks, fixedDelay tasks — each with lastExecution statusThe lastExecution block includes status: SUCCESS, ERROR, or STARTED (still running). Poll this endpoint and alert when a task's status is ERROR or its lastExecution timestamp is older than expected.
How do I add a heartbeat to a Spring scheduled task?
Ping an external monitor at the end of the scheduled method. Spring only calls this method when the scheduler is running, so a missed ping catches a scheduler that stopped or a task that threw:
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
@Component
public class NightlyReportTask {
private static final String PING_URL = "https://ping.cronshield.com/<your-check-id>";
@Scheduled(cron = "0 0 3 * * *") // 03:00 every day
public void runNightlyReport() {
doTheWork();
// Report success last. An exception above skips this call.
try {
HttpClient.newHttpClient().send(
HttpRequest.newBuilder(URI.create(PING_URL)).GET().build(),
HttpResponse.BodyHandlers.discarding()
);
} catch (Exception ignored) {}
}
}How does Micrometer observability help?
Spring Framework 6.1+ adds Micrometer Observation support to @Scheduled tasks. Each execution emits a timer metric (spring.scheduling.task) with outcome=SUCCESS or outcome=ERROR tags. Export these to Prometheus or your metrics backend and alert on a non-zero error rate or on a task that hasn't executed in longer than its schedule interval.
Add a missed-run alert to this job
The free tier gives you a heartbeat endpoint and an email alert when an expected ping doesn't arrive. Paid tiers add the log-aware diagnosis — the last log line and a likely cause in the alert. The heartbeat receiver ships in an upcoming release; see the plans to learn what each tier adds.
Frequently asked questions
- Does Spring retry a @Scheduled task that threw an exception?
- No. By default a @Scheduled method that throws an exception logs the error and does not retry. The next scheduled execution fires at the normal time. To add retries, use Spring Retry's @Retryable annotation or handle exceptions inside the method.
- What happens to @Scheduled tasks during a rolling deploy?
- If a task is mid-execution when the pod is replaced, it is interrupted without completing. The next execution fires on the new pod on schedule. Add a heartbeat to detect the gap, and set a grace period wider than your deployment window.