Revue and growth
I mentioned a few weeks ago that my cockroach-esque strategy of "just stay alive while competitors flame out" had led to another recent success, this time coming from Revue (and Twitter in general)'s general cacophony over the past six weeks.
This framing — one that has deeply impacted my product approach — I owe to idlewords aka Maciej Ceglowski aka Pinboard. I remember reading Pinboard's blog literally a decade ago and marveling at the general independent SaaS shtick and thinking it was beyond my wildest capabilities, and how there had to be some mysterious trick beyond "wait for competing applications to stumble and/or fail".
To wit, this quote of his from a few years ago has always rung true:
Running an online service solo puts one in the coffin corner between the Dunning Kruger effect and impostor syndrome. On some days you feel the correct but paralyzing sense that you are in way over your head. On other days, you'll feel like you're surfing on waves of liquid competence, doing flips, until you destroy something important.
Anyhoo: this has been the fastest few weeks of MRR growth in Buttondown's history, both in absolute and relative terms. It has been a big ol' stress test of manual systems: subscriber importing, for instance, has been fine with nary a hitch. What has really been painful has been the long tail stuff — domain integration debugging, adding VAT details, jumping on calls to debug CSS and Zapier woes, that sort of thing. This is more annoying because it's hard to engineer my way out of it, and it's equally hard to point to an easy thing to hire away. The most high-leverage hire I can make would basically be a 'full-stack customer support engineer', someone who could spend twenty hours a week jumping between the codebase and customers. This sort of skillset strikes me as, well, a valuable one — basically I want a senior engineer who won't spend much time coding. That...will not be trivial.
(On the domain integration debugging bit, though — complaining about this on Twitter led me to DNS Helper, which is the most excited I've ever been to sign up for a SaaS. Talk about a niche!)
The poorly-named django-ninja is now live and in production. If you made an external API call to Buttondown in the past week (or went to the settings or tags pages, because a few internal pages use the 'external' API) you have hit it. The good:
- It is about twice as fast as the old API. This is not for the usual second system reasons of "well, you rewrote a thing without the warts, of course it'll be faster" — it comes from Cython and serialization speed-ups, which is quite nice. This will be particularly good as I move the more mission-critical internal views, like subscriber listing and email updating, onto it.
- I now have a legitimate canonical OpenAPI spec that powers the internal application and docs. It still has many warts, but it's a step-function change over the previous spec.
The bad: the long tail of weird cases and rough edges. I would probably not recommend using django-ninja right this second unless you have the specific combination of reasons I had (speed + schema generation), but in a year or so I think it will be a very good choice indeed. I do not see myself writing any new django-rest-framework code for the indefinite future.
(The real question, as is always the case: do I regret spending the time, knowing what I now know? I do not think so — I probably would have approached it differently, but it was the right investment decision.)