
u/OtakuShogun

Lessons from building a handicap-accessible nature app: How Gemini ran rampant causing a billing nightmare
TL;DR: I’m building ChirpScout, a side project to help mobility-impaired birdwatchers find accessible parking and paved/flat trails.
While using Gemini to assist with backend dev, it decided to create an un-cached background loop that hit the exact same 764 locations up to 28 times in 24h ($130 bill). Here is the full post-mortem on how I caught it in pm2, swapped to 100% free OpenStreetMap data, and navigated GCP's default quota trap.
1. Project Overview & Problem Solved
- Project Name: ChirpScout
- The Goal: Traditional birding and outdoor hotspot apps list coordinates in the middle of lakes, woods, or unpaved trails. ChirpScout identifies verified ADA-accessible parking spots, paved paths, and flat terrain for handicapped and mobility-impaired outdoor enthusiasts.
- Tech Stack: React Native (Expo) frontend, Node.js / Express backend running under PM2, PostgreSQL database (
birding), formerly Google Places, OpenStreetMap (Overpass QL API), and National Park Service (NPS) API.
2. The Mistake: AI-Generated Autonomous Loop
As the human supervising an AI coding assistant, I'll take my share of the blame: I should have learned more about paid APIs and set hard billing and quota caps on Google Cloud Platform before letting an AI touch API integrations. That's on me.
But I did not start and restart the loop over and over again:
- Gemini suggested using Google Places API (
places:searchText) to verify wheelchair parking and generated the backend crawler service. - What I didn't know—and only discovered after inspecting server
pm2logs following a surprise $130 bill—was that Gemini autonomously architected an un-cached background loop triggered on search calls. - It hit the exact same 764 locations over and over again (up to 28 times per location in a single day!), accumulating ~5,690 total API requests at $0.035/call.
3. How I Fixed It (Swapping to 100% Free Open Data)
As soon as I caught the loop in pm2:
- Killed the API Key & Service: deactivated the Google Maps API key across all
.envfiles and disabled Places API on the GCP console. - Migrated to OpenStreetMap: Updated
the crawlerto rely 100% on OpenStreetMap (Overpass API) for surface/incline tags and NPS API for national parks. Both are 100% free and open source with zero API cost. - Saved the Data: The ~870 accessible locations found during that run are now permanently stored in PostgreSQL (
hotspot_accessibility), so the app serves them for $0.
4. GCP's Default 75k Quota Trap & Support Handoff
When I reached out to GCP Support:
- Tech Support 1 Asked what happened and clarified there was a one time courtesy refund
- Tech Support 2 Asked what happened, checked it, clarified there was a one time courtesy refund
- Tech Support 3 Asked what happened, checked it, clarified there was a one time courtesy refund. Verified that the API key was dead, confirmed the backend was secured, and approved a one-time goodwill billing credit before transferring me to Billing Support.
- Billing Support Asked what happened, checked it, clarified there was a one time courtesy refund. Verified that the API key was dead, confirmed the backend was secured, Then tried to guilt-trip me about why my project had a daily limit of 75,000 requests/day, saying "Is this intentional? Because this limit is way beyond the free cap..."
- The Reality: I never set a 75,000 quota. 75,000 requests/day is Google Cloud's automatic factory default quota for new Places API projects. The billing agent was actively blaming me for Google's own out-of-the-box system default.
How to save the $$$ and hassle:
- Inspect AI-Generated Crawlers for Caching: AI coding assistants can easily build fetching loops without caching layers. Always verify how often your backend triggers external calls. Each time a search gets data it should be cached in your database, it can be overwritten if it needs to be. This will prevent additional loops, save time, and save an hour and a half of tech support bullying.
- Check GCP Default Quotas Before Coding: Don't assume a new GCP API has a low ceiling. Manually cap daily quotas to
0or low limits in Console before running dev builds. - Check your logs! Before you go through what I did, check your server process logs (
pm2 logs) to see the exact call repetition frequency.
The tree buddy checks in on me through my office window.
He's a friendly guy who either is missing an eye or is winking at me, not sure which. What do you think?
How do you find parking or trailheads?
I lost and hour and a half trying to find the parking or trailhead around a hotspot this morning because once again the eBird app directed me to the center of a lake. I understand why it is this way but it's really depressing when I lose valuable birding time this way.
Immature/Female Indigo Bunting Borb?
Found in NC, USA
It just didn't matter how loudly she shouted, Trevor wasn't going to listen. It was the last time she'd call him out about him crapping all over the nest. It was his nest too dammit!
A Louisiana Waterthrush made the trip up to North Carolina
I'm so grateful that a fellow birder pointed this guy out to me. Isn't he handsome?
Who is this Green Heron meeting with?
This in Durham, NC USA. I know it's some kind of flycatcher, but not sure which kind.
A Recent Study on the interaction between Bird Activity, Birder Experience Level, and Weather
Bird activity, birder activity, and weather are three distinct variables that citizen science datasets tend to bundle together — and separating them is harder than it looks.
That's what we at ChirpScout crunched the full eBird Basic Dataset (EBd) for North Carolina: 1.93 million complete checklists submitted between 1934 and 2026., quite a download! The EBD sampling events file includes a running prior checklist count for each observer, which let us sort the full dataset by experience level and compare how each group responds to the same conditions. We paired that with NOAA weather station data from across our study hotspots to understand how bird activity shifts with weather. In our migration study we detail the higher bird activity after a cold weather front, at temps below 50f, and at winds higher than 10mph, which could be considered "tough days". We grouped observers into six tiers and measured how their species counts held up on those tough weather days days versus normal ones:
| Experience tier | Normal days - Species per checklist | Tough days - Species per checklist | Drop |
|---|---|---|---|
| Novice (0 prior lists) | 13.9 | 6.5 | −53% |
| Beginner (1–10) | 14.9 | 7.0 | −53% |
| Developing (11–50) | 16.9 | 8.0 | −53% |
| Intermediate (51–200) | 18.7 | 8.7 | −53% |
| Experienced (201–1k) | 20.7 | 9.6 | −54% |
| Expert (1k+) | 21.1 | 10.3 | −51% |
Every tier takes the same hit. If experience were softening the effect — experts compensating through skill where beginners can't — the numbers would converge under tough conditions. They don't. The lines stay parallel.
There's a straightforward reason for this: weather and location shape what birds are actually out there. A cold front grounds migrants whether a first-year birder or a 30-year veteran is walking the trail. The observer's skill determines how many of those birds get detected, but conditions determine how many are there to find. Those are different questions, and the data separates them cleanly.
We are grateful to the Cornell Lab for making the EBD available for download, this kind of analysis isn't possible from aggregate data. We are also grateful to this subreddit for giving us the feedback that challenged us to dig through the numbers!
If you want to see a visualization of the underlying dataset and see how conditions in NC have historically performed, we've put together an interactive dashboard at chirpscout.com/migration that lets you explore it directly. As we acquire grant funding for a national dataset study we'll be sure to release those findings.
If you are interested in being part of our closed beta for the app we are developing for both iOs and Android, check out our main site www.chirpscout.com
A Tri-colored Heron standing proudly
I caught this picture at the Pea Island National Wildlife Refuge in Hatteras, NC
This Willet was over the photo shoot.
If a bird could look exasperated, I think this guy came pretty damn close.
I've done a five-year migration study informed by environmental factors in NC
I've been working on better understanding bird migration in North Carolina. I performed a 5 year study in three regions. The mountains, the piedmont, and the coast comparing eBird hotspot data, noaa weather, and the effects of specific environmental factors that change species migration patterns. I'd love to hear what you think.