Google Sheets Trigger returning intermittent 503 Service Unavailable across multiple workflows over 24+ hours

Describe the problem/error/question

My Google Sheets Trigger node (polling every minute, rowAdded event) is intermittently failing with a 503 error across two separate workflows watching two different Google Sheets under two different OAuth2 credentials. This has occurred repeatedly from July 12 06:56 through July 13 23:03.
I’ve already checked the standard causes before posting:
Both Google Sheets OAuth2 credentials show “Account connected” with no reauth needed.
n8n’s own status page shows one incident (20 minutes on July 13, 10:58 to 11:18 in local time), but it does not overlap with any of my error timestamps.
Google Workspace’s status dashboard shows Sheets as healthy for the entire period.
Retry On Fail was already enabled on one of the two affected workflows before these errors started, and the errors persisted anyway, so this doesn’t appear to be a normal transient blip that retries can absorb.
I found two similar past threads (linked below) where the suggested fix was enabling Retry On Fail, but since that was already on for one of my workflows and didn’t help, I wanted to flag this as a possibly different or more persistent issue.
Related threads I found:

Google Sheets Trigger executions - Could not complete

What is the error message (if any)?

{
“errorMessage”: “Service unavailable - try again later or consider setting this node to retry automatically (in the node settings)”,
“errorDescription”: “The service is currently unavailable.”,
“errorDetails”: {},
“n8nDetails”: {
“n8nVersion”: “2.29.8 (Cloud)”,
“binaryDataMode”: “filesystem”
}
}

Please share your workflow

(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and 

CMD+V/CTRL+V to copy and paste the workflow.)

Share the output returned by the last node

Not applicable. The trigger node itself fails before returning any output, so no downstream node executes.

Information on your n8n setup

    1. n8n version: 2.29.8
    2. Database (default: SQLite): n8n Cloud managed
    3. n8n EXECUTIONS_PROCESS setting (default: own, main): default (Cloud managed)
    4. Running n8n via (Docker, npm, n8n cloud, desktop app): n8n Cloud
    5. Operating system: n8n Cloud

@Kalon

Polling every minute is resource-intensive and prone to these errors. The most robust way to handle “Row Added” events is to have Google Sheets push the data to n8n instantly using a simple Google Apps Script.

  1. Replace your Google Sheets Trigger with a Webhook Node in n8n.
  2. Copy the Production Webhook URL.
  3. In your Google Sheet, go to Extensions →→ Apps Script and paste a script similar to this:
function onFormSubmit(e) {
  var url = "YOUR_N8N_WEBHOOK_URL";
  var options = {
    "method": "post",
    "contentType": "application/json",
    "payload": JSON.stringify(e.values)
  };
  UrlFetchApp.fetch(url, options);
}
  1. Set up an Installable Trigger in the Apps Script dashboard (the clock icon) to run the onFormSubmit function “On form submit” or “On change.”

Welcome @Kalon!

The 503 here is coming from Google’s API, not n8n - the Sheets polling trigger calls the Sheets API on each interval and Google sometimes drops requests at the service edge even when the public status page looks green. Two things to check: first, look at the raw error body in the execution log - if it includes backendError or serviceUnavailable in the JSON, that confirms Google’s backend is the culprit. Second, try switching the polling interval to every 5 minutes instead of every 1 minute - aggressive polling with multiple credentials hitting the same Sheets API quota can compound this. If you need near-real-time detection, switching to a webhook-based approach via Google Apps Script (fires your n8n webhook on sheet change) is much more reliable than polling and avoids this class of error entirely.

Hi @Kalon
If both credentials are the “Sign in with Google” managed OAuth2 type, they run through n8n’s shared Google client on Cloud, which is why two different accounts fail in the same windows and why you have no API dashboard to look at. Recreate the credential as Custom OAuth2 using a client from your own Google Cloud project and point both workflows at it. Then open APIs and Services > Google Sheets API > Metrics in that project: the response code breakdown shows the reason Google attaches to each 503, and your polls run against your own client instead of a shared one.

The 503 is coming from Google’s side, not n8n — and on n8n Cloud, the Sheets Trigger uses n8n’s shared Google OAuth client, so you’re sharing that client’s API quota with every other Cloud user. When Google throttles that shared project, you get intermittent 503s even though your own credentials and volume are fine. That’s why it hits both workflows under different creds at the same time, and why Retry On Fail doesn’t clear it — a polling trigger doesn’t re-scan the rows it skipped during the failed cycles, so the real risk here is silently missed rows, not the error line itself.

Two fixes, in order of impact:

  1. Move to Custom OAuth2 — create your own Google Cloud project + OAuth client and use that as the credential. This takes you off the shared quota onto your own, which usually kills the intermittent 503s outright.

  2. Replace the poll with a push — a Google Apps Script onChange trigger that POSTs new rows to an n8n Webhook. No polling means no missed-row window (wrap the Apps Script side in try/catch, since it has its own quotas).

Either way, add a small safety net: a scheduled workflow every 15–30 min that re-reads the last hour of rows and de-dupes on the row id or a timestamp column — so anything dropped during a 503 window still gets picked up.

The shared-OAuth-client explanation above is very likely right, and moving to a custom client is the correct next step. But everyone here (me included, until I re-read your post) is arguing about which poll to fix, and I think the more useful question is why you are polling at all.

rowAdded at a 60-second interval is n8n asking Google “has anything changed?” 1,440 times a day, per workflow, forever — and the overwhelming majority of those calls return nothing. Every one of them is a chance to eat a 503, and moving to your own OAuth client narrows that exposure without removing it, because 503 is what Google’s backend returns under load regardless of whose client you are.

Push instead of poll. In the sheet: Extensions → Apps Script, then something like:


function onRowAdded(e) {
  UrlFetchApp.fetch('https://<your-n8n>/webhook/<path>', {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify({ range: e.range.getA1Notation(), values: e.range.getValues() })
  });
}
```

...bound as an installable trigger (Triggers → Add Trigger → On change, or On form submit if the rows arrive from a Form). In n8n, swap the Sheets Trigger for a Webhook node.

What that buys you: **zero Sheets API calls**, so the entire class of failure you're chasing disappears rather than getting rarer. Apps Script runs *inside* Sheets and doesn't touch the Sheets REST API or its quota, so a Google API 503 can't drop your event. It's also instant instead of up-to-60-seconds late, and it costs nothing.

Two honest caveats, because this isn't free:

- `onChange` does not fire for edits made by *other* API writes or scripts. If some rows arrive via the Sheets API rather than a human or a Form, those won't trigger it — check how the rows actually get there before you commit.
- You now depend on your webhook being reachable. Apps Script won't retry meaningfully, so an n8n restart during a POST loses that event.

Which is why the safety-net sweep suggested above stays regardless of which trigger you use: a scheduled workflow that re-reads the last N rows and de-dupes on a row id. Push for latency, sweep for correctness. That combination is what I'd run in production, and it's what makes "did I silently miss a row during a 503 window?" a question you can actually answer instead of assume.

One last thing worth checking before you move on: during those failure windows, did any rows actually get *missed*, or did the next successful poll pick them up? The 503s are noisy and annoying, but silent data loss is the thing that would actually hurt you, and it's worth confirming which one you had.

@Kalon
The 503 Service Unavailable error in n8n (Google Sheets Trigger) indicates a temporary issue on the destination server’s side—in this case, the Google Sheets API is temporarily unable to process the request.

The causes and solutions can be broken down as follows:

What Causes It?

  1. Google Server Overload or Temporary Downtime (Transient Error): This is the most common cause. Google’s servers might be restarting, undergoing maintenance, or handling an unusually high volume of traffic at that specific moment.

  2. Polling Too Frequently: The workflow checks for updates every 1 minute. Running a polling trigger at this high frequency can cause the Google API to view the requests as too aggressive, temporarily dropping the connection to prevent overloading (even if it doesn’t explicitly return a 429 Too Many Requests error).

  3. Intermittent Network Issues: There could be a brief connectivity drop or handshake timeout between your n8n instance and Google’s servers.

How to Fix It?

1. Enable “Retry On Fail” (As recommended by the system) This is the most effective way to handle these types of transient errors.

  • Go to the Node Settings (gear icon) of the Google Sheets Trigger.

  • Turn on Retry On Fail.

  • Configure the number of retries (e.g., 3 times) and the wait time between attempts. This prevents the workflow from immediately crashing when hitting a temporary 503 error.

2. Increase the Polling Interval If your trigger checks for data too frequently (like every minute), consider extending the interval to reduce the overall API load.

  • Change the interval to check every 5 minutes or 15 minutes if real-time updates aren’t strictly necessary for your use case.

3. Check Google Cloud Console Quotas If you are using your own custom OAuth2 credentials (rather than n8n’s default cloud credentials):

  • Log into the Google Cloud Console and check the Quotas section for the Google Sheets API to ensure you aren’t hitting per-minute or per-day limitations.

4. Check Google’s Service Status Sometimes Google Workspace itself experiences disruptions. You can monitor the real-time health of their services on the Google Workspace Status Dashboard. If Google is having a widespread outage, you will just need to wait until their team resolves the issue.

I think there are a couple of things getting mixed together here.

A 503 is usually a transient Google-side failure, but I wouldn’t automatically group it together with quota issues or aggressive polling. If Google thinks you’re exceeding quotas, you normally see 429 or quota-related 403 responses, not 503.

Also, I’m not convinced that enabling Retry On Fail is necessarily the answer here if the failure is happening at the trigger polling level itself. Trigger nodes behave differently from regular workflow nodes, so it would be useful to confirm whether retries actually apply to Google Sheets Trigger polling failures or only to downstream node executions.

The shared OAuth explanation feels much more plausible, especially since multiple users seem to be seeing this around the same time. Moving to a custom OAuth client isolates you from shared client behaviour and is probably the first thing I’d test.

That said, I think the more important question is the one Adam raised earlier:

Did anything actually get lost?

Were rows missed permanently, or did the next successful poll simply catch up and process them normally?

Because there’s a big difference between:

  • noisy transient 503 errors in the logs, and
  • silent data loss.

The first is annoying.

The second is a production issue.

Regarding the Apps Script suggestion, there is one important detail worth mentioning:

e.range and e.values work for certain trigger types such as On form submit, but they are not guaranteed to exist for a generic On change installable trigger. So the example implementation may work perfectly for some workflows and fail immediately for others depending on how rows enter the sheet.

The webhook approach is still attractive because eliminating polling eliminates the entire class of polling failures, but it introduces a different failure mode instead:

if the webhook endpoint is unavailable during delivery, Apps Script won’t give you durable retries or queueing.

Personally I’d run:

  • push/webhook delivery for low latency,
  • idempotent processing using a row ID,
  • and a scheduled reconciliation workflow that rechecks recent rows periodically.

Push for speed.

Sweep for correctness.

That combination survives API hiccups, webhook downtime, workflow restarts and pretty much every ugly edge case that eventually shows up in production.

At this point I’d be interested in three things before drawing conclusions:

  1. Shared n8n OAuth or custom OAuth?
  2. Were any rows actually missed?
  3. Are all affected users running in the same n8n Cloud region or infrastructure?

Those answers probably tell us whether we’re looking at expected Google transient failures or an actual n8n-side incident worth investigating further.

Hi Kalon,

A 503 Service Unavailable error typically indicates that the Google Sheets API server is temporarily overloaded or enforcing hard rate limits due to high concurrency.

Since you are polling every 1 minute across multiple separate workflows and OAuth credentials, it is highly likely you are triggering Google’s concurrent request quotas, causing them to reject the requests intermittently. Since “Retry on Fail” with default short delays isn’t catching it, the block duration is outlasting the retry attempts.

Here are two ways to permanently resolve this issue:

  1. Dynamic Polling & Exponential Backoff (Quick Fix):
    • Go to the Google Sheets node settings → Under “Retry on Fail”, increase the Max Attempts to 5.
    • Increase the Retry Delay (Wait Time) to at least 5000ms or 10000ms. This gives the Google API enough cooldown time between retries to absorb the transient 503 block.

  2. Shift from Polling to Push Architecture via Webhooks (Recommended :rocket:):
    Instead of having n8n poll Google Sheets every minute, you can reverse the architecture.
    • Replace the Google Sheets Trigger with an n8n Webhook node.
    • Add a simple 5-line Google Apps Script (onEdit trigger) to your Google Sheets that automatically fires a POST request to your n8n Webhook whenever a new row is added.

This completely bypasses the polling rate limits, eliminates the 503 errors entirely, and saves a massive amount of n8n execution overhead.

Let me know if you need help structuring the Google Apps Script setup, I can share the script block with you!