Skip to content
LastPing
GUIDE · GOOGLE CLOUD SCHEDULER · FREE

Monitor Google Cloud Scheduler jobs: detect missed and failed runs

Google Cloud Scheduler fires HTTP targets, Pub/Sub topics, and Cloud Run Jobs on a schedule. It retries on failure, but sends no notification when retries are exhausted. The execution history in the console shows FAILED, but nobody is watching. Add one ping call to your Cloud Function or Cloud Run handler: if the job succeeds, the ping arrives; if it fails, hangs, or was never invoked, silence opens an incident.

Your assistant can do this for you

Monitor my Cloud Scheduler jobs with LastPing

On this page
  1. Setup: one function call, about a minute
  2. What this catches
  3. Questions people ask

Setup: one function call, about a minute

Copy-paste snippets for Cloud Functions (1st gen and 2nd gen), Cloud Run Jobs, and direct HTTP targets.

Create a heartbeat monitor in LastPing

In the console, create a monitor. Cloud Scheduler uses 5-field unix cron with an optional IANA timezone: use the same expression and timezone as your scheduler job. Set the grace window to the expected maximum function runtime.

# Cloud Scheduler cron examples (5-field unix cron):
# 0 3 * * *         → 03:00 daily (in the job's configured timezone)
# 0 */6 * * *       → every 6 hours
# 30 9 * * 1        → 09:30 every Monday
https://ping.lastping.dev/<your-monitor-id>

Cloud Functions (Python): ping on success

Store the monitor ID in a Secret Manager secret or environment variable and call the ping at the end of a successful handler. Cloud Scheduler HTTP targets expect a 2xx response: return it after the ping.

import os
import flask
import requests

PING_URL = f"https://ping.lastping.dev/{os.environ['LASTPING_MONITOR_ID']}"

def scheduled_job(request: flask.Request):
    # Arm overrun detection (optional)
    requests.get(f"{PING_URL}/start", timeout=10)

    try:
        do_work()  # your actual logic here
        requests.get(PING_URL, timeout=10)
        return "OK", 200
    except Exception as e:
        requests.get(f"{PING_URL}/fail", timeout=10)
        return str(e), 500  # non-2xx → Cloud Scheduler retries

Cloud Functions (Node.js): ping on success

const PING_URL = `https://ping.lastping.dev/${process.env.LASTPING_MONITOR_ID}`;

exports.scheduledJob = async (req, res) => {
  await fetch(`${PING_URL}/start`);  // arm overrun detection

  try {
    await doWork();                   // your actual logic here
    await fetch(PING_URL);
    res.send('OK');
  } catch (err) {
    await fetch(`${PING_URL}/fail`);
    res.status(500).send(err.message);  // non-2xx → retry
  }
};

Cloud Run Job: shell script entrypoint

If your Cloud Run Job uses a shell script or container entrypoint, the same curl pattern as cron works:

#!/bin/sh
# entrypoint.sh for a Cloud Run Job
PING_URL="https://ping.lastping.dev/${LASTPING_MONITOR_ID}"

curl -fsS -m 10 --retry 3 -o /dev/null "${PING_URL}/start"

python /app/backup.py
rc=$?

curl -fsS -m 10 --retry 3 -o /dev/null "${PING_URL}/${rc}"
exit $rc
# Pass the env var when creating the Cloud Run Job
gcloud run jobs create my-nightly-job \
  --image gcr.io/my-project/my-job:latest \
  --set-env-vars LASTPING_MONITOR_ID=<your-monitor-id> \
  --region us-central1

Direct HTTP target: ping LastPing directly

If your Cloud Scheduler job calls a simple HTTP endpoint that already performs the work, you can add LastPing as a second HTTP target via a Cloud Workflows orchestration, or set the target to a Cloud Function wrapper that calls the real endpoint and then pings LastPing.

The simplest option for a small job: make the scheduler target a Cloud Function that calls your real endpoint and pings on success, as shown in step 2.

What this catches

  • Handler exception: /fail fires; Cloud Scheduler retries (up to 5); incident opens on first failure.
  • All retries exhausted: silence after the last failed retry → incident opens.
  • Function timeout: /start arrived, function killed by timeout → overrun detection opens incident.
  • Scheduler job paused or deleted: no invocation in the window → incident.
  • Recovery: next successful run closes the incident automatically.

On AWS instead? See AWS Lambda + EventBridge. On Azure? See Azure Functions timer triggers. For the concept behind why absence is the reliable signal, see dead-man's switch explained. AI agents can use the LastPing MCP server to report heartbeat directly.

Questions people ask

Front-loaded answers: the most important fact first.

  • Does Google Cloud Scheduler alert on failure?

    No, not by default. Cloud Scheduler retries HTTP targets with exponential backoff (configurable, up to 5 times). If all retries fail, the job is marked as FAILED in Cloud Scheduler's execution history, but no notification is sent. You need either a Cloud Monitoring alerting policy on the scheduler/job/attempted_job_count metric (complex) or a dead-man's-switch ping inside the handler that fires only on success (simple, this guide).

  • How do I monitor a Cloud Scheduler job that calls a Cloud Function?

    Add one HTTP call at the end of the Cloud Function handler that fires only when the function completes successfully. For Python: import requests; requests.get('https://ping.lastping.dev/<id>', timeout=10). For Node.js: await fetch('https://ping.lastping.dev/<id>'). Create a LastPing heartbeat monitor with the same schedule and a grace window equal to the expected function runtime plus some buffer. If the ping doesn't arrive, an incident opens.

  • What cron syntax does Google Cloud Scheduler use?

    Cloud Scheduler uses standard 5-field unix cron format: minute hour day-of-month month day-of-week. For example, 0 3 * * * means 03:00 daily. Importantly, you can set an IANA timezone per job (e.g., America/New_York) rather than being forced into UTC. This is one of Cloud Scheduler's advantages over AWS EventBridge, which only supports UTC.

  • How many retries does Cloud Scheduler do?

    Configurable per job. The default is 0 retries. You can set up to 5 attempts with exponential backoff. A non-2xx HTTP response or a Pub/Sub message that isn't acknowledged counts as failure. If all attempts fail, the job is FAILED in the history, with no notification.

  • How do I detect a Cloud Run job that hangs?

    Send a /start ping at the beginning of the handler and set the LastPing grace window to the Cloud Run job timeout. Cloud Run Jobs have a configurable timeout (default 10 minutes, up to 168 hours). If the job exceeds its timeout, Cloud Run kills it before the success ping fires. The /start arrived but no success follows, so overrun detection opens the incident.

  • Can I use Cloud Scheduler to ping LastPing directly (without a Cloud Function)?

    Yes, if your entire job is the HTTP call to LastPing. More practically: if your scheduled work is a Cloud Run service or App Engine handler, you can add the LastPing ping as the last HTTP call inside that handler and return 200 only after both complete. Or set a Cloud Workflows definition that calls your endpoint and then pings LastPing.

  • Is this free?

    Yes. LastPing is free for individuals with no monitor cap. See vs Healthchecks.io and vs Cronitor.

FREE FOR INDIVIDUALS · FULLY HOSTED

Cloud Scheduler fails silently. Add one line to know immediately.

One function call at the end of your handler. First alert in under a minute, and LastPing monitors itself the same way.