Paternity leave has been a strange cocktail of much-needed work hiatus mixed with insane struggle to keep a larvae-stage human alive. Sleep is scarce but adrenaline flows to compensate, an involuntary reaction dads have when we hear babies cry. Preemies need warmth and protection from other people’s germs, so we're stuck in-doors. I’m starting to resemble Jack Nicholson in The Shining. I need something to do.
To pass the time, I devised a Node.js app to help me score a table at State Bird Provisions. A while back, I noticed their online reservation system was pretty clunky. I planned to make the app ping their reservation page periodically, hoping to discover the time when new openings were made available. With that tidbit of knowledge, I would have an edge when booking a table, or so I thought.
For the unfamiliar, State Bird Provisions boasts inventive, modern food and, for a twist, serves it up dim sum-style from carts that roll by your table. The flavors and format garnered attention from the food media, culminating in last year’s 'Best New Restaurant' nod from Bon Appétite. As a result, seats in this hot-shit San Francisco eatery are harder to come by than affordable apartments. Drive by any day of the week and you’ll see a line of people snaking down the block waiting for the doors to open. It makes me sad to see the desperate foodies hoping for one of the few walk-in tables, phones out and photo apps at the ready. Food shouldn't be this hard.
I built the Node app to check the reservations page every minute and then log the findings. I let it run for a few days and then—excited to apply my data scientist skills for something useful—checked the logs. Instead of a predictable pattern of daily openings coming available, the data revealed that tables rarely opened up. When they did, it was one table at a time, not a bank as I expected. The timing was erratic; one would appear at 11:15AM, another at 7:22PM, and another at 11:06PM. Though, they never materialized between midnight and 11:00AM. Sometimes a day or more would pass without a nibble. The most shocking discovery was this: when a table finally did come available, it was off the market again within sixty seconds. The scientific term that best describes my initial reaction is: WTF?
I considered the data further and deduced two things. First, the random table openings were from cancellations. Clearly the nice folks at SBP were using the phone to book months in advance and then throwing late cancellations over to the online system. Second, I wasn’t the only nerd with a penchant for trendy restaurants working this angle. Whereas my simple app hunted for patterns, the other bots in the mix obviously completed the booking process. That explains the open tables appearing so briefly. To test this theory, I bumped up the frequency of my pings and saw new seats disappear within 20 seconds! Never one to be outdone, especially where deep-fried quail is concerned, I dove back into my app and extended the functionality.
I beefed up the program but it felt wrong to programmatically complete the transaction. Deciding to leave a bit of the human element in tact, my app checked the page often and, when an opening was detected, sent an SMS to my phone using Twilio’s API. The text message contained a pre-formatted URL which, when tapped, took me directly to the reservations page. If a more aggressive bot hadn’t already snatched the prize, I needed only tap a “Submit” button to be on my way to haute cuisine heaven.
It worked like a charm. After a few days, I scored a four-top for my Dad who was holding onto a gift certificate to State Bird for almost a year. He had almost given up on actually redeeming it. I nabbed another for me and the wife—now we just need a sitter. One more came in which I passed along to a coworker. Then I turned it off.
It was a fun distraction and working in Node was a blast (I rarely get to code these days). I loved the feeling I was beating the system. However, guilty feelings crept in one day after driving past that snaking line of hungry wanna-bes. "This is too much power for one man to posses" I thought to myself. "Besides, I have diapers to change".