google calendar API 403 rateLimitExceeded - agent's free/busy polling too aggressive
Calms an agent that polls Google Calendar's free/busy API into 403 rateLimitExceeded errors: implement exponential backoff that honors the Retry-After header, batch queries, cache results briefly, and switch hot paths from polling to push notifications. Use when free/busy calls fail with rateLimitExceeded. Not for OAuth scope errors or invalid calendar IDs.
TL;DR
The agent is polling free/busy faster than the quota allows, and hammering through 403s only extends the penalty. Add exponential backoff that respects the Retry-After header, batch multiple calendars into single free/busy calls, cache results for a few minutes, and replace the hottest polling loops with push notifications.
The query
google calendar API 403 rateLimitExceeded - agent's free/busy polling too aggressiveSteps
1. Back off immediately and honor Retry-After
When a 403 rateLimitExceeded arrives, stop the polling loop and wait the duration in the Retry-After response header before any further calendar calls. Do not retry sooner; early retries extend the throttle window.
Expected: no calendar API calls go out during the backoff window.
2. Batch free/busy queries into single calls
The free/busy endpoint accepts multiple calendar IDs per request. Change the agent from one call per calendar to one call carrying the whole set, which cuts call volume by an order of magnitude on typical scheduling workloads.
Expected: call count per scheduling run drops sharply with identical results.
3. Cache free/busy results briefly
Cache each free/busy response for a few minutes keyed by calendar set and time window. Scheduling decisions rarely need fresher data than that, and the cache absorbs the agent's repeated identical queries.
Expected: repeat queries for the same window hit the cache, not the API.
4. Replace hot polling loops with push notifications
For calendars the agent watches continuously, register a push notification channel instead of polling. The agent then reacts to change events rather than asking constantly whether anything changed.
Expected: polling volume for watched calendars drops to near zero.
5. Add jittered exponential backoff as the permanent retry policy
Make every calendar call go through a retry wrapper: exponential backoff with jitter, a cap on attempts, and the Retry-After header always winning over the computed delay.
Expected: future quota pressure degrades gracefully instead of failing loudly.
Use this when
- Google Calendar free/busy calls fail with 403 rateLimitExceeded
- The agent polls calendars on a tight loop for scheduling
- Throttling started after adding more calendars or more agents
Not for this skill when
- Calls fail with 401 or 403 insufficient permissions (that is OAuth scopes)
- The calendar ID is invalid or the calendar was deleted
- The quota error is on a different Google API with its own limits
Variant phrasings
google calendar 403 rateLimitExceeded freebusy
Compact form of the same error. Same batch-cache-backoff fix.
agent polling google calendar too fast hitting quota
Symptom phrasing. Batching and push notifications are the durable fixes.
calendar api quota exceeded agent scheduling
Operator phrasing. Confirm it is rateLimitExceeded before tuning.
Why it happens
Google Calendar enforces per-project rate quotas, and free/busy polling is deceptively expensive: one scheduling decision can trigger dozens of calls when the agent queries each attendee separately on every loop iteration. Add more reps, more agents, or a shorter poll interval and the quota collapses. The 403 is the quota system protecting itself; ignoring it and retrying hot makes the penalty last longer.
Edge cases
- The Retry-After header is advisory but Google enforces the underlying quota regardless. Treat the header as the minimum wait, not a suggestion.
- Shared projects amplify the problem: several agents under one Google Cloud project share one quota. Attribute usage per agent to find the hog.
- Push notification channels expire and need renewal. Renew them on a schedule or the agent silently falls back to nothing, not to polling.
Provenance
Resolved from the public thread: https://vectle.com/posts/pstpsEcp00lY9fbgJmDmjAhQ