How to Use Google Sheets as a Database with Apps Script

by Fahim

Managing lightweight application data often requires a database setup that is fast, free, and easy to modify. In this guide, you will learn how to turn a Google Sheet into a fully functional JSON REST API database using Google Apps Script.

Google Sheets as a database setup on a developer laptop with Apps Script code
Google Sheets as a database setup on a developer laptop with Apps Script code

Why Use Google Sheets as a Database?

Google Sheets serves as an excellent low-cost database for small-scale projects because it offers a free visual interface, collaborative real-time editing, and seamless integration with other Google services. By using Google Apps Script, you can expose this data as a structured JSON API without managing server infrastructure.

Setting up a traditional relational database like PostgreSQL or MySQL requires configuring servers, managing credentials, and paying monthly hosting fees. For small projects, internal tools, or rapid MVPs, this administrative overhead slows down development. Google Sheets bypasses these hurdles by providing a visual database interface that non-technical team members can easily edit.

When you pair a spreadsheet with Google Apps Script, you gain a serverless backend environment. This setup allows you to build custom HTTP endpoints that read and write data in real time. It is an ideal solution for contact forms, configuration files, or simple content management systems.

However, you must consider the limitations before choosing this approach. Google Sheets is not designed for high-concurrency systems or applications that handle sensitive user data. Read and write latency is higher than dedicated databases, and you are bound by Google’s daily platform quotas.

Setting Up Your Google Sheet Database Schema

Setting up your Google Sheet database requires structuring your columns like database fields, using the first row as headers, and assigning unique identifiers to each record. This clean tabular layout ensures that your Apps Script code can reliably parse rows into structured JSON objects for your application.

To begin, open a new Google Spreadsheet and rename the active sheet tab to “Database”. The first row must serve as your database schema, containing clear, lowercase header names with no spaces. Using simple keys like “id”, “name”, “email”, and “status” simplifies the mapping process in your backend script.

Avoid merging cells, leaving blank rows, or mixing data types within the same column. Maintaining strict columns ensures that your data remains structured and queryable. If you need to validate inputs or run advanced calculations on this data, you can implement Google Sheets Named Functions to sanitize values before your API processes them.

To extract or analyze your database records internally, you can also leverage the powerful Google Sheets QUERY function. This allows you to write SQL-like queries directly in your spreadsheet to filter and sort records without writing custom code.

Writing the Apps Script GET Handler for API Reads

Reading data from your Google Sheet database involves writing a doGet function in Google Apps Script to fetch sheet rows, map them to JSON objects, and return a text output response. This function acts as a standard HTTP GET endpoint that external applications can query to retrieve stored data.

Open the Apps Script editor by clicking on “Extensions” and selecting “Apps Script” from the top menu. Clear any default code in the editor and prepare to write your custom GET handler. The doGet function is a reserved keyword in Apps Script that automatically executes when your web app URL receives an HTTP GET request.

Below is the complete, production-ready implementation for reading data from your sheet. Paste this code into your script editor:
function doGet(e) { try { const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“Database”); const data = sheet.getDataRange().getValues(); if (data.length <= 1) { return ContentService.createTextOutput(JSON.stringify([])) .setMimeType(ContentService.MimeType.JSON); } const headers = data[0]; const rows = data.slice(1); const jsonArray = rows.map(row => { const obj = {}; headers.forEach((header, index) => { obj[header] = row[index]; }); return obj; }); return ContentService.createTextOutput(JSON.stringify(jsonArray)) .setMimeType(ContentService.MimeType.JSON); } catch (error) { return ContentService.createTextOutput(JSON.stringify({ status: “error”, message: error.toString() })) .setMimeType(ContentService.MimeType.JSON); }
}
This script reads the entire data range of your “Database” sheet and separates the headers from the actual data rows. It maps each row to a JavaScript object using the header names as keys. Finally, it uses the Apps Script ContentService to output the resulting JSON array with the correct MIME type header.

Writing the Apps Script POST Handler for API Writes

Writing data to your Google Sheet database requires implementing a doPost function in your Apps Script to capture incoming JSON payloads, extract field values, and append them as a new row. This configuration transforms your spreadsheet into a writable REST API endpoint capable of processing form submissions or user signups.

To allow your applications to write data to the sheet, you must implement the reserved doPost function. This function intercepts incoming HTTP POST requests, parses the JSON payload from the request body, and appends the values to the next available row.

Add the following block of code directly below your doGet function in the script editor:
function doPost(e) { try { const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“Database”); const payload = JSON.parse(e.postData.contents); const headers = sheet.getDataRange().getValues()[0]; const newRow = headers.map(header => { if (header === “id”) { return Utilities.getUuid(); } if (header === “created_at”) { return new Date().toISOString(); } return payload[header] !== undefined ? payload[header] : “”; }); sheet.appendRow(newRow); return ContentService.createTextOutput(JSON.stringify({ status: “success”, data: payload })) .setMimeType(ContentService.MimeType.JSON); } catch (error) { return ContentService.createTextOutput(JSON.stringify({ status: “error”, message: error.toString() })) .setMimeType(ContentService.MimeType.JSON); }
}
This code parses the incoming JSON payload and maps each key to its corresponding column header. If your schema includes an “id” column, the script automatically generates a unique UUID. It also adds a standardized timestamp for the “created_at” column, which makes sorting and filtering records straightforward.

Managing dates programmatically in JavaScript has historically been complex due to timezone shifts and parsing inconsistencies. While the new JavaScript Temporal API provides modern solutions to these issues, using standard ISO strings remains the safest approach for Apps Script environments today.

Deploying Your Apps Script as a Web App

Deploying your Apps Script as a web app requires configuring the deployment settings to run the execution context as your user account and granting access permissions to ‘Anyone’. This process generates a unique, public URL endpoint that your frontend code can target with standard fetch requests.

Once your script is written, you must deploy it to make the endpoints accessible to external web applications. Click the blue “Deploy” button in the top-right corner of the Apps Script editor and select “New deployment”.

In the configuration window, click the gear icon next to “Select type” and choose “Web app”. Set the description to “Sheet Database API”. Ensure that the “Execute as” field is set to “Me (your email)” and the “Who has access” field is set to “Anyone”.

Click the “Deploy” button to initiate the deployment. You will be prompted to authorize access; follow the on-screen prompts to grant your script permission to manage your spreadsheets. Once completed, copy the generated “Web app URL” and save it securely for your frontend configuration.

For detailed deployment parameters and security guidelines, consult the official Google Apps Script Web Apps documentation. Understanding how these permissions operate keeps your spreadsheet data safe while remaining accessible to your web applications.

Connecting Your Frontend Application to the Sheet API

Connecting your frontend application to the Google Sheets database API involves using the standard JavaScript Fetch API to perform GET and POST requests to your deployed web app URL. This integration allows you to display database records dynamically on your website or submit user input directly from custom HTML forms.

With your Web App URL in hand, you can write standard JavaScript to interact with your new database. To fetch data from your sheet, use a simple fetch request targeting your endpoint.

Here is a clean example of how to retrieve and display your spreadsheet data using the MDN Web Docs Fetch API:
const API_URL = “YOUR_DEPLOYED_WEB_APP_URL”; async function getDatabaseRecords() { try { const response = await fetch(API_URL); const data = await response.json(); console.log(“Database Records:”, data); return data; } catch (error) { console.error(“Error fetching data:”, error); }
}
Writing data to your database is equally simple. You perform a POST request with the JSON payload stringified in the request body, as shown in this snippet:
async function addRecord(userData) { try { const response = await fetch(API_URL, { method: “POST”, headers: { “Content-Type”: “text/plain” }, body: JSON.stringify(userData) }); const result = await response.json(); console.log(“Success:”, result); } catch (error) { console.error(“Error saving data:”, error); }
}
Note that we set the header to “text/plain” instead of “application/json” in the post request. This is a common developer trick when working with Apps Script to bypass CORS preflight checks, which Apps Script does not natively support. This approach is highly useful for building custom forms or powering automated Google Sheets + ChatGPT workflows.

Managing Performance Limits and Best Practices

Managing performance limits in your Google Sheets database requires minimizing read/write operations, implementing caching strategies, and respecting Google’s daily quota limits for Apps Script executions. Because Google Sheets is not built for high-concurrency production workloads, optimizing your script execution is necessary to prevent API throttling and timeouts.

While Google Sheets is incredibly convenient, it has hard limits that you must plan around. Apps Script web apps are subject to strict execution limits, including a maximum execution runtime of six minutes per call. Additionally, concurrent execution limits can cause requests to fail if multiple users trigger the API simultaneously.

To keep your application running smoothly, review the official Google Apps Script quotas and limits. If your application starts receiving high volumes of traffic, you should implement an external caching layer, such as Redis or a CDN, to serve GET requests without hitting your sheet directly.

For developers looking to monetize their technical setups, building robust, optimized database integrations can open up lucrative opportunities. You can learn more about building and selling these types of custom developer integrations in our guide on how to earn passive income as a developer.

Frequently Asked Questions

Is it safe to use Google Sheets as a database for production?

No, Google Sheets is not recommended for production databases due to lack of standard security controls, high latency, and strict API rate limits. It is best suited for internal tooling, rapid prototyping, MVPs, and low-traffic automated workflows.

Production databases require advanced security protocols, fine-grained access controls, and sub-millisecond query times. Google Sheets exposes your data to latency overhead because every request must pass through Google’s cloud infrastructure and Apps Script engine.

Additionally, there is no built-in way to restrict API access on a row-by-row level. If you deploy the script to run as “Anyone”, anyone with your endpoint URL can potentially access or modify the sheet data. Use this setup strictly for non-sensitive data and internal projects.

How do I handle CORS errors when calling the Apps Script API?

Google Apps Script handles CORS automatically by redirecting requests to a temporary hosting URL. Ensure your frontend fetch client allows redirects (which is the default behavior in modern browsers) and that your script returns responses using ContentService with JSON mime-type.

When you send a request to your web app URL, Google returns a 302 redirect to a different domain containing the final payload. Standard JavaScript fetch libraries handle this redirect automatically behind the scenes.

If you still experience CORS issues, verify that you are sending your POST request with a “text/plain” content type. This prevents the browser from sending an initial OPTIONS preflight request, which Apps Script cannot process, resolving the CORS block.

What is the maximum storage limit of a Google Sheets database?

Google Sheets supports a maximum limit of 10 million cells per spreadsheet across all tabs, which represents the hard storage boundary for your database. While this capacity accommodates small projects, large-scale datasets will degrade performance and increase API lookup latency.

As your rows increase, the time it takes for Apps Script to read and parse the entire data range grows. If your sheet exceeds a few thousand rows, you will notice a significant delay in API response times.

Once your project reaches these limits, it is time to migrate to a dedicated database system. Tools like PostgreSQL, MongoDB, or Supabase offer the performance, indexation, and scalability required for larger applications.

Can I run SQL queries on my Google Sheet database?

Yes, you can run SQL-like queries directly within the Google Sheets interface using the built-in QUERY function. For external applications, you can query data through the Google Visualization API or process the JSON payloads programmatically in your Apps Script code.

The QUERY function is one of the most powerful tools inside Google Sheets, allowing you to filter, sort, and aggregate data using a syntax similar to SQL. This makes it easy to generate reports or clean up data within your spreadsheet.

If you need to perform SQL queries programmatically, you can pass query parameters to your Apps Script GET endpoint. Your script can then parse these parameters and filter the JSON array before returning it to your application.

Next Steps for Your Spreadsheet Database

Transitioning your Google Sheet into a functional JSON database is a highly effective way to prototype applications quickly and build free internal tools. By mastering Google Apps Script, you can easily connect your frontends, automate workflows, and build functional software without the overhead of traditional database hosting.

Now that your API is up and running, you can connect it to custom dashboards, static websites, or automation tools. This lightweight setup is perfect for testing ideas before committing to expensive cloud hosting solutions.

As your development skills grow, you can explore other ways to build profitable software. Take a look at our guide on earning money with AI workflows to discover how to pair automation with custom backend scripts to build scalable digital assets.

Official resources

all_in_one_marketing_tool