Don't Say the M Word
This is the lightning talk I gave at ElixirConf 2024, “Don’t Say the M Word.”
More Testing, Fewer Tests
These are the slides for my ElixirConf 2024 talk, “More Testing, Fewer Tests.” These slides probably don’t make a ton of sense on their own—you’ll also need the code samples, particularly the test directory.
Why Elixir Is the Best Language for Building a Bootstrapped, B2B SaaS in 2024
[This article is the companion to my presentation for CodeBEAM America 2024, Elixir is the One-Person Stack for Building a Software Startup. You can download the slides as a PDF or view them in Google Slides.]
I’d like to share why I chose Elixir as the programming language (and really, as we’ll discuss, the full stack) for SleepEasy, the website monitoring SaaS I’m building. I’m going to do my best to focus on the objective features of the language which make it particularly suitable for a small, nimble team starting a software business.
Because SleepEasy is B2B software, a web app is absolutely required. At some point in the distant future, a mobile app may be too, but I expect to get by without mobile for a long time. Even if I do one day need a mobile app, a simple wrapper around a web view will probably suffice.
The fact that I’m bootstrapping this company (that is, self-funding to start and growing it solely from the business’s own profits) sets one other major requirement: the app needs to be able to be built and maintained by a team of one, at least for the first few years or the first $10k+ in monthly revenue.
Continue reading…Acquisition Channel Determines Pricing (And Product)
This week, I launched a demo feature for SleepEasy to make it really easy for prospective users to see what the app can do for their site. Right at the top of the home page, you just drop in your site’s URL and we’ll check:
- Uptime (is your site working at all?)
- Broken links (we’ll try to load the first 5,000 links, images, scripts, etc.)
- HTTPS support (to make sure your SSL/TLS certificates aren’t going to expire and thereby break access to your site)
- Domain registration (to make sure a missed renewal doesn’t cause you to lose access to your domain)
Through social media, I got about 30 people to try their site—not a bad amount of traffic, I thought, but only one of those 30 actually created an account (a free account!). That is, only one person cared enough about this stuff to sign up for alerts when we found issues. Of course, I already knew the people in my network are not my target market, but this was just further evidence.
So I need to shift my focus fully to marketing, and specifically to traffic acquisition. I need to get SleepEasy in front of people who:
- Know they have a need for website monitoring
- Know they lose money when there are issues with their site
- Have had issues with site reliability in the past
I have ideas on where to find people like that, but they aren’t going to be the people I originally intended to sell SleepEasy to. Let me explain…
Continue reading…Making Web Scraping Super Reliable
Two of the core features of SleepEasy—uptime checks and broken link checking—are built on web scraping. In this last half of December, as I gear up for a big marketing push and public signups, I’ve been doing a lot of work to get these features really dialed in and reliable.
Continue reading…Rapid Unscheduled Learning
There’s a joke in rocket engineering that you never say something exploded, you say it underwent a rapid, unscheduled disassembly. In the same way, I experienced some rapid, unscheduled learning this last week with SleepEasy.
Continue reading…I Launched SleepEasy to Early Access Users aaaaand...
Last week I soft-launched SleepEasy to people on my early access list. I had a small email list of about 30 people who had signed up because they wanted SleepEasy to monitor their domain, and in the course of talking about the early access launch, another 10 or so people joined that list.
So, how did it go? How many people signed up?
Keep in mind, I was launching to an intentionally small group. I wanted to shake out any issues before opening it up to a wider field. I figured I’d be lucky to get 5-10 signups.
Well, out of those 40 or so people…
[Drumroll, please! 🥁 🥁 🥁]
Continue reading…Build vs. Buy for a Bootstrapped SaaS
Since I made the decision to go independent and build SleepEasy, I’ve faced a couple points where I needed to decide whether to build a particular feature from scratch myself or buy someone else’s code to do the job.
In my years of working at small software shops, the common refrain was that we would consider buying tech to solve a problem if it wasn’t core to our business or part of our unique selling proposition. I don’t really feel like that principle applies at the MVP stage of SleepEasy, though. As I’ll discuss below, I happily considered shelling out to a third party for a core feature of my app, just because the value to customers is in the way that feature gets wired up to their web site. At this stage of the product, having something to fill a gap is better than spending months trying to make the best, most unique version of a feature.
Unsurprisingly, cost is also a much bigger factor for me than it was at my Real Jobs™. When you’re paying a developer, say, $15k/month, it’s easy to justify spending thousands of dollars buying a solution if it lets you use that developer’s time for something else. In my case, of course, SleepEasy’s current lifetime revenues amount to $0, so that calculus doesn’t quite work the same. At the same time, though, there’s an opportunity cost to me not having a Real Job. Every month I’m trying to bootstrap SleepEasy is a month my family is foregoing tens of thousands of dollars, so if the business is going to fail, it’s better to do so quickly. The right amount for me to be willing to spend, then, is not $15k per month of dev time saved, but it’s also quite a bit higher than $0.
So that’s where my head has been on these things. I have three examples I can share for how those ideas have worked out.
Continue reading…On MVPs and Cutting Scope
Eric Ries’ book The Lean Startup popularized the idea of the minimum viable product: the smallest version of a product that allows the creator to learn about the market, their customers’ needs, and what the next steps should be. Over the last week, I’ve really shifted my idea of what “minimum” means with respect to SleepEasy’s MVP—what’s really required for customers to get value out of it and for me to get feedback.
It started with asking myself: if I commit to shipping by December 1 to early access customers, what can I push back and what absolutely must be ready if the product is going to be worth paying for?
Continue reading…A Prepostmortem: Why SleepEasy Will Fail
There’s an exercise for founders that strikes me as really valuable:
Suppose it’s a year from now and the business has failed.
Why did it fail?
This is surprisingly insightful. In the case of SleepEasy, the biggest risks are not technical… after all, I’m basically building a Cadillac version of website monitoring. There are certainly some interesting technical challenges (we’ll get to those), but it’s not like I’m trying to build a wearable lapel pin to replace the smartphone. 👀
Continue reading…Fantastic Hacks and Where to Find Them
These are the slides for my talk at the Denver Erlang and Elixir Meetup from November 6, 2023.
- Download the Keynote file (23 MB)
- Download the PDF (4 MB)
Naming Products Is Hard
As you may know, last week I sort of quit my job to start a website monitoring service.
The key differentiators of that service are:
- “Done for you”—you just point us at your domain, and the monitoring just works… no configuration necessary.
- Capable of way more advanced checking than competing services, including running login, account creation, and ecommerce/billing flows against your live site.
- No false positives—all issues get reviewed by a human before alerting your team.
That service now has a name and a web site (yay!). If you’re interested, you can sign up there to get in on the early access program as soon as it’s ready.
I thought I’d share a bit about how I came to the name, and some of the challenges I ran into getting there.
If you’ve never tried to name a service, it’s kind of miserable. You’re putting your blood, sweat, and tears out into the world, and you have 2-4 words with which to pique someone’s attention enough to get them to look deeper into what you’re offering. The perfect name will:
- Communicate what your thing is or does
- Communicate why someone would want it
- Be memorable
- Not be a mouthful
- Have a matching domain available, ideally
.com
- Be unique—not just among product names, but among all trademarks, which may include regional consultancies that use your would-be name as a tagline on leaflets at the local chamber of commerce (but I’m not bitter 😒)
It’s easy enough to satisfy some of those, but all of them is pretty much impossible. That’s led to me spending an absolutely embarrassing amount of time digging through trademark and domain registries trying to find the perfect name.
In my service’s short life, it’s gone through 3 names and 3 brand identities. First, I was calling it “Is Prod Okay?”, a name I rather like for appealing to SaaS folks, but I worried the name would be alienating if it turned out that ecommerce shops running something like WordPress were a better client base. Next, it was just called “Site Monitor.” It certainly communicates what the thing does, and I did like the potential SEO benefits of the name being an exact match for a bottom-of-funnel search term. Ultimately, though, that name leaves a lot to be desired on the branding front… it certainly doesn’t communicate the benefits of the service or what makes it unique from dozens of competitors.
Then, inspired by a discussion with Andrei Soroker on Elixir Outlaws, I wanted to call it “SleepWell.” That did a good job of explaining the benefits—you can have confidence your site’s core flows are working as intended—but unfortunately there’s already a company in the monitoring space using the name. Same goes for “RestAssured” and other variants.
That’s how I got to “SleepEasy.” I’m not in love with the name (a friend teased that it sounds like a bad translation), but it’ll do for now. It gets at the benefits, and you certainly can’t fault it be not being unique. There are still a handful of names I’m kicking around that I might eventually pivot to, but for now, I have to cut myself off and get back to building the damn thing. An imperfect name won’t make or break the service, but not getting it in front of customers will. I’m steeling myself for a future “SleepEasy is now _________” email, though. 🤪
I’m definitely interested to hear any feedback you might have on either the name or the site!
Continue reading…A Scary Story
In the spirit of Halloween, I’d like to tell you a scary story. This one, though, is all the more scary because it’s true.
It was a dark and stormy night, and two software developers were working late to ship a new internal service for their team. The finishing touch was to add production tokens for Google OAuth so their peers could sign in without manually creating an account.
They slowly opened the GCP console, the web page loading so slowly you could almost hear it creeeeeeak across the wire.
“This storm must be messing with the wifi,” said the senior dev. “Weird.”
Continue reading…Going Indie and Building in Public
I sort of quit my job.
I say “sort of” because I’m going to be gradually winding down my work on Felt, where I’ve been for the past couple years, in order to gradually ramp up the amount of time I spend working on my own business.
That business is a new take on website monitoring. Existing monitoring focuses on uptime (“is my site down”), which is fine, and sort of table stakes. But I think there’s a market for being way, way more proactive about monitoring… alerting you before there are problems, or alerting you about things that might be damaging to your business or your reputation, but which aren’t captured by the most basic “is the site responding at all?” checks. At the same time, existing solutions are just massively more complex than they need to be… starting from the way they bill (“$x/month for y monitors”) through the amount of configuration required to get them to just do what you want (“tell me if my site is broken”). And don’t even get me started on the false alarms… in the course of my career, I’ve had maybe 10× more wakeup calls at 2 in the morning from false alarms in a monitoring service than actual issues with my website!
So I’m building a site monitoring service… it’s going to be:
- Absolutely dead simple—just tell us the web site you want us to monitor and we do the rest
- Way more capable than any other service on the market (for instance, maybe your web site is online, but one of your business’s key user flows isn’t working—login, new account signup, checkout, billing, etc.—we’ll alert you about that)
- Guaranteed to never produce a false alarm—if you get a 2 am phone call, it’s because your stuff is actually having a critical incident!
Rebuilding the Plane While It’s Still Flying
This is the slide deck from my conference talk at ElixirConf 2023.
The talk references this little microframework we put together to implement David Bernheisel’s “Batching Deterministic Data” recipe from his Safe Ecto Migrations series.
A microframework for backfill migrations in Elixir's Ecto
This is a tiny little to-purpose framework for data migrations we’ve used at Felt. It’s based on David Bernheisel’s outstanding Safe Ecto Migrations series, specifically his Batching Deterministic Data pattern for backfill migrations.
Continue reading…Releasing CBTea, a Cognitive Behavioral Therapy Journal
I recently released my first side project in years.
CBTea is a privacy-first tool for doing cognitive behavioral therapy (CBT) automatic negative thought records.
The idea here is that you:
- Record a negative thought
- Categorize it into a few common cognitive distortions
- Come up with some “challenges” to push back on the automatic thought
- See if you can find a new way of thinking about the situation that’s more healthy/accurate
The app is based on an old open-source mobile app called Quirk CBT, which was amazing in its day… and then they took VC funding and had to try to turn it into a business. 😭
I have big plans for the future… I’d like to add end-to-end encryption, support for using it without creating an account at all, offline support, and so on. The GitHub issue tracker has the world’s most basic roadmap.
A Brief Guide to Hiring in Niche Languages Like Elixir
I had someone tell me their company is considering moving away from Elixir because they’re worried they can’t hire enough devs. (They currently employ, um, 3.)
This is a bad reason to move!
Instead, here’s a brief guide to hiring in niche languages, using Elixir as an example.
At this point, I’ve seen a handful of companies execute on maybe half these strategies half well. Every single one of them had more qualified applicants than they could hire. (Which means they got to be extremely choosy about who they picked!)
Continue reading…TIL about ExUnit's global assert_receive_timeout default config
We’ve had a persistent problem at work with Elixir tests of Phoenix Channel interactions failing in CI only. The simplest push + reply you can imagine may, due to the vagaries of low-end, shared CI hardware, wind up taking a full second to receive a reply. 🥴
I’d been fixing these one at a time by adding a third timeout parameter to my assert_receive, assert_push, assert_reply, and assert_broadcast calls.
TIL you can instead just do:
config :ex_unit, assert_receive_timeout: if(ci?, do: 2_000, else: 100)
(In the main ExUnit docs, search for :assert_receive_timeout
.)
Phoenix LiveView 0.19.5 and later include my very modest PR to use this as the default timeout for LiveView’s message-receiving test functions too (assert_patch
, assert_redirect
, assert_push_event
, and assert_reply
).
TIL: use copy()
in the JavaScript console
TIL that from a browser’s JavaScript console, you can use the copy()
function to write a value directly to your clipboard.
I’ve been using the mouse to highlight the output for so long!