Side Hustle
Thursday. team lunch.
Six people. Long table. Nemesis across from me.
Great. At least there are mozerella sticks.
Someone asks about my app.
"Still doing that?"
"Yeah. It's live."
Live for nine months. The AWS bill is unfortunately low.
"What's it do again?"
"Quotes and invoices for independent businesses. Jobs. Deposits. Customer stuff."
"Any customers?"
"Uhh, some users. Finding a market fit."
I take a bite. Should end here.
"How many?"
"Four... organizations."
Actually four accounts. One is expired, one is my test account.
"Paying?"
"One is on a trial."
"Free trial?"
"For now"
I feel good about the trial to paying customer trajectory on this account.
Silence.
Nemesis saves us. Says he builds furniture on weekends.
Sorry what.
"Like a hobby?" someone asks.
"Mostly commissions."
Of course they're commissions.
Tables. Cabinets sometimes. He shows a photo.
Phone goes around the table. Comes to me last.
Walnut dining table. Big. Actual joints.
"Nice," I say.
too fast. It is nice though.
"I don't really advertise," he says. "Mostly referrals. I'm booked through March."
March. It's August.
Someone asks how he tracks the jobs.
Spreadsheet. Invoices separately. Photos in folders.
"My app does that," I say. "And software scales."
why add scales. Get it together.
Nemesis looks over.
"What's it called?"
I tell him.
He takes out his phone. Shit. It's fine. Normal interest.
Thirty seconds maybe.
My phone starts screaming.
Not buzzing. PagerDuty siren. Full volume.
Whole table stops. Table beside us too. Restaurant stops. World stops.
My watch starts going too. Hard little vibration against the table.
I set critical alerts to ignore silent mode. Phone and watch. Redundancy.
P1 — signup-api returning 500
I cover the screen with my hand.
Watch shows the same alert.
Other hand.
Both hands now hiding one signup.
"Work thing," I say.
They are not fooled. They are work things.
Nemesis is looking at his phone.
"I think that was me."
No.
"Could be unrelated," I say. "These alerts are... aggregate."
Aggregate?
He turns his phone toward me. My signup form. Red error at the top.
"Probably correlated."
Stop. Smug bastard.
I acknowledge the page. The restaurant becomes quiet again.
Laptop open.
Stack trace is immediate.
Cannot read properties of undefined (reading 'trim')
I angle the laptop away from the table. Toward Nemesis, unfortunately.
"Schema issue," I say.
Nemesis looks at his phone.
"I left company name blank. It said optional."
"It is optional. At the UI layer."
layer. stop talking about layers.
"The service still normalizes it."
Normalizes nothing apparently.
Code is one line.
const companyName = input.companyName.trim()
No default. No question mark. Damn.
PagerDuty escalation has three steps. Push, phone call, SMS.
Code has zero checks.
I add a default in the schema. Test the empty field. deploy.
"Try again," I say.
Nemesis submits.
My phone buzzes normally.
new trial
"Works," he says.
Five accounts.
Software scales.
Nemesis looks through a few screens.
"I'll probably keep the spreadsheet," he says. "I mostly wanted to see the flow."
"Yeah. It makes more sense once you have some volume."
why say volume to the man booked through March.
8:43 that night. I check the account.
customers imported: 38
jobs imported: 17
invoices created: 4
Four invoices. Today.
I open billing settings.
free trial: 14 days
Fourteen seems high.
I change it to seven.
Save.