Cloud Scheduler
Cloud Scheduler is cron-as-a-service. Define a cron schedule, point it at an HTTP endpoint, a Pub/Sub topic, or an App Engine handler, and it triggers on the cadence you specify. No VM to keep running, no missed-tick worry on infrastructure failure — Google runs the scheduler, you only see the firings.
The trap most teams fall into is putting business logic in the scheduler job itself. Scheduler is a trigger; the work belongs in a separate service (Cloud Run, Cloud Functions, a Cloud Workflows execution) that the scheduler invokes. That separation gives you retry, observability, and the ability to invoke the same work outside the schedule when you need to.
Cron at GCP Scale
Cloud Scheduler removes the operational tail of running cron jobs: no host to patch, no missed firings during maintenance, no clock-drift surprises. It charges a small per-job monthly fee — usually negligible compared to the operational savings. For any recurring trigger that today lives in a crontab on a VM, the migration is mechanical.
Targets: HTTP, Pub/Sub, App Engine
HTTP targets call an arbitrary HTTPS endpoint — typically a Cloud Run service or Cloud Function. The right default. Attach an OIDC token for private destinations. Pub/Sub targets publish a message to a topic when the schedule fires — useful for fan-out, where several subscribers should each react to the scheduled tick. App Engine targets exist for legacy App Engine workloads; do not pick them for new work.
Cron Expressions and Time Zones
Cloud Scheduler accepts standard 5-field unix-cron expressions (shortcut aliases like @daily are not supported). Every job carries a time zone — the default is UTC, which is rarely what a user-facing scheduled action wants. A job that should run at 3 AM local time fires at 3 AM UTC unless you set the time zone explicitly. This is the most common Cloud Scheduler bug: a daily report that always lands at the wrong hour because nobody changed the time zone.
Retry Policies
Each job has its own retry config: retry_count, min and max backoff, max retry duration, max doublings. The default is retry_count of 0 — a failed attempt is not retried at all; the job simply waits for its next scheduled run. For idempotent jobs (most reports, ETL kicks, cache refreshes), set an explicit retry count with exponential backoff to handle transient endpoint failure. For non-idempotent jobs that should not be redone, keep the zero default and handle failure alerting elsewhere.
Recurring vs One-Off
Cloud Scheduler is for recurring schedules — same job, repeated cadence. For a one-off deferred dispatch ("send this reminder email at 9 AM tomorrow"), Cloud Tasks with schedule_time is the cleaner fit: each task has its own retry policy and ack, no cron expression to manage, and the task disappears after it runs. Use Scheduler when the cadence is genuinely periodic.
- Leaving the default UTC time zone on a job that should run at a local-time hour — the report lands six or eight hours off, every day, until someone notices.
- Putting business logic in the target endpoint without a retry policy. A transient 5xx kills the run; the next firing is hours away.
- Schedule cadence shorter than the typical job runtime. Runs overlap, two copies write the same row, the database doesn't take it kindly.
- Using Cloud Scheduler for a one-off deferred dispatch where Cloud Tasks with
schedule_timeis the right tool. - HTTP targets to private endpoints without OIDC tokens — every firing returns 401, no one notices because the schedule is silent on failure.
- No monitoring on Cloud Scheduler job execution. Failed jobs are invisible unless you alert on them.
- Target a Cloud Run service or Cloud Function with an idempotent handler. Never put significant logic in the scheduler job itself.
- Set the time zone explicitly on every job. UTC for system-internal cadences; local time zone for user-facing actions.
- Use Pub/Sub targets when several components should react to the same scheduled tick — Scheduler publishes once, every subscriber gets it.
- Explicit retry config:
retry_count, min/max backoff, max retry duration. Match retry duration to the cadence so failed runs do not retry past the next scheduled firing. - OIDC tokens for HTTP targets to private endpoints.
- Cloud Monitoring alert on job execution failure. A schedule that fires silently into the void is worse than no schedule at all.
Knowledge Check
What is the default time zone for Cloud Scheduler jobs?
- The time zone of the GCP region where the job is created, inherited from the region you pick at creation
- UTC — set the time zone explicitly when a job needs to fire at a local-time hour
- The time zone configured in the project's metadata defaults
- America/Los_Angeles, matching Google's headquarters
For triggering one-off deferred work ("send this reminder in 24 hours"), which service is the cleaner fit than Cloud Scheduler?
- Cloud Workflows — its long-running executions handle deferred dispatches naturally
- Cloud Tasks with
schedule_time— each task has its own retry policy and disappears after it runs - Eventarc — register a one-shot trigger that fires exactly once at the configured future wall-clock time
- Pub/Sub with a delayed publish — set the publish time in the future
A Cloud Scheduler job targets a Cloud Run service deployed with --no-allow-unauthenticated. The job fires every minute and every dispatch returns 401. What is the typical cause?
- The Cloud Scheduler service account is missing the project-level Editor role, so the dispatch is rejected before it ever reaches the service
- The job is not configured with an OIDC token; requests reach the private endpoint without authentication
- Cloud Scheduler cannot target private Cloud Run services regardless of authentication setup
- The schedule expression is invalid and is being interpreted as "every 60 seconds in error mode"
Why target a Pub/Sub topic with Cloud Scheduler instead of directly calling an HTTP endpoint?
- Pub/Sub targets are cheaper than HTTP targets in Cloud Scheduler
- A scheduled Pub/Sub publish fans out to every subscriber, so multiple components can each react to the same tick independently
- Cloud Scheduler cannot retry HTTP targets at all; only Pub/Sub targets carry a retry policy, so any job that needs redelivery on failure must publish to a topic
- HTTP targets have stricter rate limits than Pub/Sub targets at high firing frequencies
What happens when a Cloud Scheduler job has a cadence shorter than the typical runtime of its handler?
- Cloud Scheduler queues the firings internally and dispatches them strictly one at a time, holding each new tick until the prior handler invocation has returned
- Runs overlap — two or more invocations of the handler can be in flight at once, a problem for any handler not built for concurrency
- The schedule throttles automatically to match the observed handler runtime
- Cloud Scheduler skips a firing whenever the previous one is still running
You got correct