A more convenient way to use Google Sheets as your backend data.
Heavily inspired by opensheet from @benborgers.
I used his service a bunch, it's very handy, but I wanted a bit more control and the possibility for something faster and more reliable to run myself.
I also plan to add a way to pass in your own API key and bypass the shared limitations.
This code was mostly vibe-coded, then loosely reviewed and cleaned up.
The main idea is to keep it super lightweight and as close as possible to "just run the binary and put it behind your usual setup".
So the flow is basically:
- get your Google API key
- make the
.env - run the binary
- expose it how you want, with your trusted reverse proxy or whatever
Create a .env file:
GOOGLE_API_KEY=your_google_api_key
PORT=8080Then run:
docker compose up -dBy default this pulls ghcr.io/devazuka/gsheet:latest.
The service listens on http://localhost:8080 by default and stores its LMDB cache in the gsheet-data Docker volume.
Then run:
docker compose -f docker-compose.yml -f docker-compose.debug.yml up --buildThis builds a debug binary inside Docker and runs /app/target/debug/gsheet, so the host does not need cargo.
GOOGLE_API_KEY=your_google_api_key cargo run --releaseOr build the binary first:
cargo build --release
GOOGLE_API_KEY=your_google_api_key ./target/release/gsheetBy default the service listens on port 8080.
Only GOOGLE_API_KEY is required.
PORTdefault8080CACHE_DIRdefault./data/heedwhen running directly,/datain DockerSHEET_MAX_AGE_SECSdefault300DOCUMENT_MAX_AGE_SECSdefault3600ERROR_MAX_AGE_SECSdefault30GOOGLE_CACHE_TTL_SECSdefault300GOOGLE_CACHE_TTL_MAX_SECSdefault1200GOOGLE_RATE_LIMITdefault300GOOGLE_RATE_WINDOW_SECSdefault60GOOGLE_MAX_QUEUED_REQUESTSdefault64
Minimal VPS flow:
git clone https://github.com/devazuka/gsheet.git
cd gsheet
printf 'GOOGLE_API_KEY=your_google_api_key\nPORT=8080\n' > .env
docker compose up -dUpdate in place:
git pull
docker compose pull
docker compose up -dGET /upGET /:idGET /:id/:sheetGET /raw/:idGET /raw/:id/:sheetGET /refresh/:id/:sheetrefreshes one sheet page on the next read by removing its cached upstream Google values
scripts/bench.sh measures the cost of turning a cached raw Google sheet response into the shaped JSON response.
It benchmarks the same sheet through:
/raw/:id/:sheet/:id/:sheet
and reports the delta.
It uses:
hyperfinefor repeated single-request timing- parallel
curlfor simple throughput/load This repo includes a small benchmark flow focused on the thing that matters here: raw cached Google JSON vs shaped JSON.
Install:
sudo apt install hyperfine jq curl python3Run:
bash scripts/bench.shIt uses .env, starts target/release/gsheet, hits the sheet from TEST_SHEET_ID and TEST_SHEET_NAME, saves JSON results in bench-results/, then opens a small viewer.
If needed:
bash scripts/bench.sh "Sheet 1"
bash scripts/bench.sh "Sheet 1" 500 1,8,32,128,256The viewer compares saved runs and shows:
- raw vs shaped throughput by concurrency
- single-request overhead
- RSS over time
- a small comparison matrix across selected runs
For function-level profiling:
cargo install flamegraphUse it with release debuginfo:
CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph --bin gsheet -- --helpOr use the helper:
bash scripts/flamegraph.shExamples:
bash scripts/flamegraph.sh shaped "Sheet 1" 20 64 1000
bash scripts/flamegraph.sh raw "Sheet 1" 20 64 1000