It texted golfers the moment a tee time opened up.
EarliBirdi was a tee-time alert service I designed, built, and ran on my own. You told it where and when you wanted to play. It watched the course's booking system around the clock and sent you a text with a booking link the moment a matching time appeared. I've since retired it. This page covers what it did, how it worked, and why I shut it down.
Alert set: Forest Park · Sat · 8–10 AM · 4 players
Fri 6:12 AM
🏌️ Tee time found!
Course: Forest Park Golf Course
Date: Sat, Oct 4
Time: 8:10 AM
Price: $38
Book now at: foreupsoftware.com/…
Booked it. 🙌
October 2026
EarliBirdi has hung up its clubs. Thanks for playing. ⛳
6:00What it did
First to know about a cancelled tee time, so you're first to book it.
Good tee times at popular public courses go fast and cancellations come back without warning. EarliBirdi watched the tee sheet so golfers didn't have to refresh it all day.
Set an alert
Search by zip or city, pick a supported course, then set the date, time window, group size and holes.
It watched every two minutes
A scheduled engine checked every active alert against the course's live tee sheet across three different booking platforms.
You got a text
When a matching time opened up, an SMS with the course, time, price and a direct booking link went out right away.
Setting an alert: course, date, time window, players, holes.
The landing page.Free and Pro plans, billed through Stripe.
6:10By the numbers
One person, end to end.
I did all of it: product, design, engineering, payments, infrastructure and support.
38courses supported across 3 regions: DC–MD–VA, South Florida, Southern California
3booking platforms integrated, each with its own API and quirks
2 minbetween checks of every active alert, around the clock
240+commits from first prototype to retirement
6:20How it worked
A small system with one job: never miss a match.
A React web app took the alerts. A scheduled engine in Google Cloud did the watching. Twilio delivered the texts.
Web appReact + MUICourse search with Mapbox, alert setup, account and billing
Data & rulesFirebaseAuth, Firestore, Cloud Functions enforcing plan limits server-side
EngineCloud Run JobsTriggered by Cloud Scheduler every 2 min; one stateless sweep per run
ProvidersAdapter layerforeUP · Chronogolf · TenFore, normalized into one tee-time shape
DeliveryTwilio SMSMatch details and a direct booking link, E.164-normalized numbers
BillingStripeCheckout, customer portal and webhooks for the Pro plan
ReliabilityHeartbeat + validatorA dead-man's switch on every sweep and a weekly probe of every course
HousekeepingExpirer jobRetired past alerts every 30 minutes
An alert that quietly never fires looks exactly like one with nothing to report. I built a validator that ran the engine's exact query against every course and flagged any that went dark, plus a heartbeat that paged me if a sweep didn't run.
Architecture
Make every platform look the same
Each booking platform had its own API, IDs and failure modes. A provider-adapter layer normalized them, so adding a course became a one-line data change instead of new code.
Infrastructure
Off the Mac mini, into the cloud
The engine started as a loop on a computer in my house. I moved it to Cloud Run Jobs on a schedule, with stateless sweeps, secrets in Secret Manager and per-commit images for one-command rollback.
Trust
Close the gaps before customers find them
Once it took payments, I audited it myself. I moved plan limits server-side, locked down database rules so no one could upgrade themselves to Pro, and normalized phone numbers so every alert reached a real phone.
6:30On the course
Built for the phone in your golf bag.
The alert arrives as a text, so you'd act on it from your phone. Every flow was designed for mobile first.
6:40Course closed
Why I retired it
EarliBirdi did what it promised. It found tee times and sent the texts, and building it taught me more about running a product than anything I could have read. I retired it on purpose, for two reasons.
The platforms caught up. When I started, booking systems treated last-minute openings as an afterthought. Over the next two seasons that changed. Courses and their booking platforms launched their own waitlists and notifications, and started restricting automated access from third-party tools. One platform put its entire tee sheet behind a CAPTCHA, and others changed their APIs without notice. The problem I set out to solve was being solved at the source, which is the best validation an idea can get.
When one platform put its tee sheet behind a CAPTCHA, EarliBirdi marked those courses unavailable instead of quietly failing.
That changed the job. Keeping alerts accurate stopped being a product problem and became a permanent integration problem: chasing undocumented changes and access rules that were never built with a partner in mind. I wasn't going to engineer around a platform's decision to limit access. An alert service that misses alerts is worse than none at all.
So rather than let it fade, I shut it down deliberately.
And my full-time work deserves my full attention. In 2026 I joined Oasis Security, now part of Cyera, where I'm a Senior Customer Success Engineer. EarliBirdi had grown into a second job. I'd rather do one job exceptionally well than two adequately. So the alerts stopped, user data was deleted, and this page replaced the app.
Your platform is someone else's roadmap.Building on access you don't control is a dependency, not an asset. Price that risk in from day one.
Reliability is the product.Users never see the adapter layer. They only see whether the text arrived. Most of my best work was invisible.
Ending well is part of building well.Shutting down cleanly, with data deleted, costs stopped and what happened written down, is a skill too.