Cloud Scheduler retryCount max 5: key the Sume submit by slot

Cloud Scheduler retries a failed target up to 5 times, and a retried call looks like a new request. Key the Sume submit by the schedule slot, not the retry.

5 min readSume
All posts

When Google Cloud Scheduler calls your endpoint to start a Sume run, derive the Idempotency-Key from the schedule slot, such as the Format and the date and hour, and never from the time of the attempt. Cloud Scheduler can retry a failed call up to 5 times, so one slot can reach your code several times. A slot-based key makes all of those the same Sume run.

The Scheduler facts are from Configuring retries for Cloud Scheduler jobs, read 2026-10-10. The Sume facts are from Create a run and Generation admission.

What are the retry settings?

The page lists retryCount, with a default of 0 and a maximum of 5, so by default there are no retries. maxRetryDuration defaults to 0s. The backoff starts at minBackoffDuration (5s by default), grows up to maxBackoffDuration (3600s) and doubles maxDoublings times (5 by default). These numbers are documented defaults; check your job's configuration for what is actually set.

As an illustration only, if each wait doubled from 5 seconds, five retries would wait 5, 10, 20, 40 and 80 seconds, about 155 seconds in total before the last attempt. The page defines the exact semantics, so use this to get a sense of scale, not as a promise.

Cloud Scheduler retry fields (Google page, read 2026-10-10)
FieldDefaultMaximum or note
retryCount0Up to 5
maxRetryDuration0sCaps the total retry time
minBackoffDuration5sFirst wait
maxBackoffDuration3600sLongest wait
maxDoublings5Number of times the wait doubles

Why does a retry matter for a paid call?

A retry happens because the target did not answer as success, and that includes cases where your code did run and call Sume, but the response never arrived. Without a stable key, the retry would start another paid run.

With the key, the repeat returns 200 with idempotency_hit: true and the original run. If the body differs, Sume answers 409 idempotency_conflict; if the first request is still being handled, 409 idempotency_key_in_use. The key lives within one Format and can be 255 characters long.

How do I build the slot?

Compute it from the intended schedule, not from Date.now(). For an hourly job, truncate the current time to the hour and format it, such as promo-2026-10-10T09. A retry 20 seconds later still lands in the same hour and maps to the same key. A retry that crosses the hour boundary is the edge case: if an attempt runs at 09:59:58 and its retry at 10:00:03, they get different keys. Read the scheduled time from the request if your target receives it, or add a small buffer and accept that a late retry may be a new slot.

Use short retry settings for a submit endpoint. The Sume request is quick, so a retry window of a few minutes is plenty, and a longer one only makes boundary cases more likely.

For a daily job, the slot is the date, and the boundary risk almost disappears. For an every-minute job, the slot is the minute, and retries across the boundary are likely, so a coarser slot or a stored last-slot marker is safer.

function slotKey(format, now = new Date()) {
  const hour = now.toISOString().slice(0, 13); // 2026-10-10T09
  return `${format}-${hour}`;
}

What about 429 from Sume?

A Sume 429 queue_full or 429 rate_limited is a retryable outcome and a good reason to let Scheduler retry. Return a non-2xx status to the Scheduler so it retries with its backoff, and honor retry-after if you wait yourself. With the slot key, the retry is safe whichever way it ends.

Mind the plan limits: Pro has a queue capacity of 20 and concurrency 4 per the admission page, so a schedule that fires many jobs at once can fill it.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume