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.


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. Execution history shows FAILED but sends no notification. 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 (simple, this guide).

  • What cron syntax does Cloud Scheduler use?

    Standard 5-field unix cron: minute hour day-of-month month day-of-week. Importantly, you can set an IANA timezone per job (e.g., America/New_York) rather than being forced into UTC as with EventBridge.

  • 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.

  • 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 and fully hosted with no monitor cap and no paid tier. See vs Healthchecks.io and vs Cronitor.

FREE · FULLY HOSTED · NO PAID TIER

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.