The Google Sheets node in n8n handles reading, appending, updating, and clearing rows without touching the API directly. The operation people usually want is append-or-update, and the mistake people usually make is not understanding how it matches rows.
Spreadsheets are the most common destination in automation because everyone can read one. The node covers the operations well, and almost all the trouble is in two places: choosing an authentication method that will not break, and understanding row matching.
Table of contents
- Authentication: pick the right one now
- The operations
- Where workflows go wrong
- A workflow shape that holds up
- Running n8n where it will keep running
- How this fits the rest of the stack
- FAQ
Authentication: pick the right one now
Two options, and the choice has consequences that show up months later.
OAuth2 connects your own Google account. Fast to set up, and it acts as you - so the workflow can reach every sheet you can. The problem is that it is tied to a person. When that person leaves, or revokes access, or changes their password in a way that invalidates the token, the workflow stops.
Service account creates a machine identity in Google Cloud with its own credentials. Setup takes longer: create the account, generate a JSON key, and share each spreadsheet with the service account’s email address exactly as you would with a colleague.
For anything running unattended, use the service account. The extra fifteen minutes buys you a workflow that does not depend on a human’s account remaining in a particular state, and access is granted per spreadsheet, which is a far tighter scope than access to everything one person can see.
The one thing people miss with service accounts: sharing. The service account has no access to anything until you share the sheet with its email address. A permission error immediately after setup is almost always this, not the key.
On credentials generally - the JSON key is a credential like any other. It belongs in n8n’s credential store, not pasted into a workflow node or committed anywhere.
The operations
The node groups operations into document-level and sheet-level actions.
- Append Row - adds a new row at the end. Always adds; never updates.
- Append or Update Row - updates an existing row when a matching column value is found, appends when it is not. This is the one most workflows should use.
- Get Row(s) - reads rows, with optional filtering.
- Update Row - updates an existing row, and does nothing if no match is found.
- Delete Rows or Columns - removes them structurally.
- Clear - empties data while leaving the sheet in place.
- Create - a new sheet within a document, or a whole new spreadsheet.
Append-or-update is the operation that makes workflows idempotent, and idempotency is what makes a workflow safe to re-run. A workflow that only appends will duplicate everything if it runs twice - after a retry, after a manual re-trigger, or after a webhook that fired twice.
It works by matching on a column you nominate. Choose a column that is genuinely unique and stable: an order ID, a customer ID, an email address. Do not match on a name, a date, or anything a person can edit, because the first time two rows share that value the behaviour becomes unpredictable.
If the node cannot do what you need, the documented escape hatch is the HTTP Request node with the Google Sheets credential selected as a predefined credential type. You get the full API with authentication already handled, which is much better than building the OAuth flow yourself.
Where workflows go wrong
Five failure modes account for most of the trouble people report.
Column headers must match exactly. The node maps fields to columns by header text, including whitespace and case. A trailing space in a header cell produces a silent mismatch - the data goes nowhere and no error is raised, which is the worst kind of failure.
Types are not preserved the way you expect. Sheets applies its own interpretation. Numbers with leading zeros lose them, long numeric strings become scientific notation, and dates are reformatted according to the sheet’s locale. If a value must survive intact - a postal code, a phone number, an identifier - format the column as plain text in the sheet before writing to it.
Rate limits. The Sheets API has per-minute quotas, and a workflow iterating over a thousand items writes a thousand times. Batch instead - collect items and write them together rather than one node execution per row.
Concurrent writes. Two workflow runs writing to the same sheet at once can interleave badly, especially with append-or-update, where one run’s read-then-write can race another’s. If a workflow can overlap with itself, either prevent that or accept the risk deliberately.
Sheets are not databases. They have row limits, they slow down substantially at scale, and they have no transactions, no indexes, and no real concurrency control. A sheet with a hundred thousand rows is a sheet that takes seconds to open and a workflow that times out.
A workflow shape that holds up
For a webhook feeding a spreadsheet, the parts that make it reliable are the ones that are easy to skip.
- Webhook trigger receives the event.
- Validate the payload before doing anything. A workflow that writes malformed data into a sheet has to be cleaned up by hand.
- Transform with a Set or Code node so the field names match the sheet headers exactly.
- Append or Update Row, matching on a stable unique identifier.
- Error branch that notifies someone. A silently failing workflow is worse than one that fails loudly, because nobody notices for weeks.
Turn on retry with backoff for the Sheets node. Transient API errors are normal and a single retry resolves most of them.
Set the workflow’s error workflow so failures reach a channel someone reads. The most common way automation fails is not dramatically - it is quietly, in the background, for a month, until someone asks why the report is missing half its rows.
Keep the sheet as an output rather than a source of truth where you can. Write records to a database and use the sheet as a view that people can read. Then a sheet someone accidentally sorts, filters, or deletes a column from is an inconvenience rather than data loss.
Running n8n where it will keep running
A workflow is only as reliable as what it runs on, and this is where self-hosted n8n setups tend to be weakest.
n8n needs somewhere persistent for its own data - workflows, credentials, and execution history. The default embedded database is fine for evaluation and is not what you want for anything you depend on. A proper Postgres instance behind it is the standard recommendation, and it is the difference between an upgrade being routine and an upgrade being risky.
It also needs to survive restarts without losing scheduled work, needs its credentials held securely, and needs to be reachable over HTTPS for webhooks to work at all - which means a domain and a certificate.
On RunxBuild, n8n is a managed tool with its own plan, custom domains, environment variables, autoscaling, and logs. Put a managed Postgres beside it and the persistence question is answered - backups, connection limits, and private networking included rather than configured. n8n on a $6 Basic plan with a managed Postgres beside it is a small monthly figure for something that otherwise means running a server, terminating TLS, and owning the upgrade path yourself.
The general point stands regardless of where you run it: the automation is only as available as its host. A workflow that quietly stopped three weeks ago because a container was rescheduled and the state was in an embedded file is a common and avoidable failure.
How this fits the rest of the stack
Automation that matters needs somewhere that stays up, keeps its state, and tells you when it fails. The RunxBuild hosting calculator shows n8n as a managed tool alongside the managed Postgres that holds its workflows and execution history, as separate line items - so the cost of running your automation properly is a number rather than a server you maintain in your spare time.
Useful related references:
- Access Blocked: Google Verification and Self-Hosted n8n Credentials
- n8n vs Make: Where the Complexity Goes
- n8n Use Cases: What It Is Genuinely Good At, and What It Is Not
- Services on RunxBuild
FAQ
Should I use OAuth2 or a service account for n8n Google Sheets?
A service account for anything running unattended. OAuth2 ties the workflow to a person’s account, so it breaks when they leave or revoke access. A service account has its own credentials and is granted access per spreadsheet, which is both more durable and a tighter scope.
Why is my n8n Google Sheets node not writing data?
Most often the column headers do not match exactly - the node maps fields to columns by header text including case and whitespace, and a trailing space produces a silent mismatch with no error. With a service account, the other common cause is not having shared the spreadsheet with the service account’s email address.
What is the difference between Append Row and Append or Update Row?
Append always adds a new row, so re-running a workflow duplicates data. Append or Update matches on a column you nominate and updates the existing row when it finds one, which makes the workflow safe to re-run after a retry or a duplicate webhook.
Why do my numbers change format in Google Sheets?
Sheets applies its own type interpretation - leading zeros are dropped, long numeric strings become scientific notation, and dates are reformatted by locale. Format the column as plain text in the sheet before writing if the exact value matters, such as for postal codes or identifiers.
Can I use Google Sheets as a database for my n8n workflow?
For small volumes and human-readable output, yes. It is a poor database at scale - there are row limits, performance degrades badly, and there are no transactions, indexes, or concurrency control. Write to a real database and use the sheet as a readable view instead.