All posts
Blog

Google Sheets as a database: when it makes sense (and when it does not)

An honest guide to using Google Sheets as a database with a REST API. Learn the good fits - prototypes, configs, human-edited data - and the real limits around concurrency, joins, and scale before you build on it.

3 min read

The appeal is real, and so are the limits

A Google Sheet is already a database your whole team knows how to use. Rows, columns, edits, formulas - no schema migrations, no hosting, no SQL. With SheetsAPI you can put a REST layer on top of any tab so your app reads and writes those rows over HTTP. The first row of each tab defines the JSON field names, so a sheet with name, email, plan returns exactly those keys.

That convenience is genuine. But "I can query it over HTTP" is not the same as "it is a good database for my workload." This post is a balanced look at where a sheet shines and where it will hurt you.

SheetsAPI is currently in beta and free while we test it, so it is a low-risk way to try the idea before committing.

Where Google Sheets is a great fit

A spreadsheet-backed API works well when data is small to medium, mostly human-edited, and read more than it is written:

  • Prototypes and MVPs. Ship a working backend in minutes, then migrate to Postgres later if the product takes off.
  • Configuration and content. Feature flags, pricing tiers, FAQ entries, landing-page copy - data a non-engineer should be able to edit in a familiar UI.
  • Internal tools and dashboards. Small datasets that a few people update by hand.
  • Form and list endpoints. Collecting signups or feedback into rows you can also eyeball in the sheet.

For these, you get filtering, sorting, and pagination out of the box. Here is a read against the REST API, searching a case-insensitive substring, sorting descending, and trimming the returned fields:

curl "https://sheetsapi.gkit.mreshank.com/api/spreadsheets/USER_KEY/Pricing?search=plan:pro&sort=-price&fields=plan,price&limit=50"

Or from JavaScript, appending a new row (POST accepts one object or an array of them):

await fetch(
  "https://sheetsapi.gkit.mreshank.com/api/spreadsheets/USER_KEY/Signups",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ name: "Ada", email: "ada@example.com", plan: "free" }),
  }
);

CORS is enabled, so you can call it straight from the browser. While your sheet is public you need no token; once you create a key, send Authorization: Bearer sk_.... See authentication for the details.

Where it is the wrong tool

Be honest with yourself before you build something load-bearing on a sheet:

High write concurrency

Spreadsheets are not built for many simultaneous writers. If dozens of clients append, update, and delete rows at once, you should reach for a real database rather than a sheet.

Relational data and joins

A sheet is a flat list of rows. There are no foreign keys and no server-side joins. You can put related data in separate tabs, but you will be stitching them together in your own code - and that gets brittle fast. Anything genuinely relational belongs in SQL.

Large datasets

The list endpoint caps limit at 1000 rows per request, and you paginate with offset. That is fine for hundreds or a few thousand rows, but it is not how you serve a large table. If you are reaching for huge offsets, the data has outgrown a spreadsheet.

Transactions and strict integrity

There is no multi-row transaction, no uniqueness constraint, no type enforcement - a cell can hold anything. If a half-finished write would corrupt your state, do not use a sheet.

A practical rule of thumb

Ask three questions: Is the data small (think hundreds to low thousands of rows)? Is it edited mostly by people, not hammered by machines? Could you live with a brief inconsistency if two edits raced? If you answer yes to all three, a sheet is a fine backend and SheetsAPI will save you real time. If any answer is a firm no, treat the sheet as a prototype and plan your migration path now.

The honest version: use Google Sheets as a database where its strengths - familiarity, instant editing, zero ops - outweigh its weaknesses, and reach for a proper database the moment scale, concurrency, or relationships dominate.

Want to try it on a real tab? Sign in with Google and point SheetsAPI at a sheet - it is free during the beta.

Share