We spent 2 years building a product that got “oohs” and “ahhs” but got no real usage.
We took all the YCombinator advice for finding Product-Market Fit: we narrowed the focus of who the product was tailored to, we generalized a few features, talked to hundreds of developers, but nothing— absolutely nothing— would stick. The product was really useful, but we misused abstraction and the product never fit a user’s value toolchain .
This is the story of how we (Brev.dev) learned the lesson of abstractions the hard way, and pivoted our way out of it!
The Origin of Brev
Our first startup, Paneau, put tablets in Ubers/Lyfts for local businesses to advertise on. With heavy physical operations, we didn’t survive the pandemic (here’s how if interested).
After Paneau died, within an hour, we had started building Brev— we desperately wanted to make it easier for ourselves of 2 years prior to build what we had built. We always overcame physical hurdles, like the time we haggled AT&T to give us 200 free tablets or snuck past Uber security to get in more cars, or when I emptied my 401K to survive one more month while we waited to hear back from YC. But solving digital problems are a different beast.
During January 2020, our first month of YC, we had a terrifying dev environment issue that took a month for us to solve. When dev environment issues strike, you have no idea how long they’re going to take, and you’re not doing creative work— it feels like blindly throwing things at a wall until something sticks. This was the only time a hurdle actually felt like it was limiting us, and those moments were excruciatingly painful— just the pit feeling in your stomach… you’re stuck! So we set out to abstract away dev environments altogether.
Brev v0: The Dream Stack as a Service
Abstractions are like rungs of a ladder, and we wanted to place the user one rung above the environment. The only way to do that is to make all the architectural decisions for you. To solve the problem of dev environments that keep causing hell, we built an IDE that prescribed to you the same stack we used to build Paneau: a NoSQL database, Python, specifically Python 3.7.5, with FastAPI as the web framework.
Because of these decisions, you never had to install anything (other than python packages you wanted)— you just went to
app.brev.dev and started coding. You also got SMS/Twilio, web argument error handling, cron jobs, and way more out of the box. You could click a big red button and instantly deploy your code. You could, or rather, we could, build our advertising startup within an afternoon.
Users built some pretty cool things! You could build an SMS chat bot within minutes. I hosted a couple virtual coding classes on Reddit where newbies who had never built anything built a fully deployed todo app after an hour.
The Problem: Where Abstractions Kill Products
Even if we found literal split images of us that wanted the Python-FastAPI-NoSQL prescribed stack, there eventually comes a time where you need to do something the makers of an abstraction didn’t intend. And this is where the abstraction fails. Let’s say you got off the ground with our prescription but then noticed your data model was slowing down your DB queries so you want to move to Mongo. Well, ya can’t. And this is where abstractions kill products.
Abstractions are really powerful when they match the problem you’re solving. But, if you do your job well, the problem you’re solving changes— for example, first building an MVP to get users to but later needing to optimize database queries because of a lot of users. And with the problem changing, the abstraction must change as well. Products shouldn’t marry an abstraction, but rather enable a user to climb up and down the ladder, being able to use only the rung that is essential to solving their current problem, abstracting away unnecessary variables.
We realized the prescription wasn’t the problem, it was the marriage to it. How can we provide the same abstraction but let users navigate the rungs at their will? In April 2021, we
rm -rf-ed our repo so that we couldn’t have a sunk cost fallacy leading us into a trap of leveraging what we had already built. We thought to ourselves, knowing what we know now, how would we approach this problem?
The New Brev: Containers for Development
We learned that the only way to win the End of Localhost is to respect a developer’s preferences— all of them. Two developers who think their favorite IDE or framework is superior are both correct.
We realized a Brev user in flow shouldn’t be doing anything different. Brev shouldn’t be a product, it should be your terminal and your environment but without your environment issues. So we pivoted Brev to be a powerful cloud computer for local development.
We now provide a dev environment (as a VM) with everything running out of the box. You can use a template of ours and it’ll just work. But, you’re the superuser of your dev environment, not us. It’s your terminal, and your same tools & IDE, not ours. We even go out of our way to help you configure an ssh proxy for your shell to boot straight into a Brev environment. We have no say, nor do we want say, in what you do on the machine or how you use it. But because we picked a better level of abstraction, you get environment branching and public port sharing and even delete your machine for a fresh one if you get yourself in a bad state. and can securely share your code for due diligence in the acquisition process
It’s funny, you could do everything right, have solid marketing and sales motions, solid product, but if your abstraction doesn’t fit a user’s value toolchain, it doesn’t matter. Hopefully you won’t make the painful mistakes we made.
If you’re building something new and wanna talk through it, please reach out! @naderlikeladder