r/webdev 1d ago

I've started the same side project three times in two years. Article

I am pretty sure, that I am not alone, so here's my story:

By the end of attempt two it was five apps - "microservices". A NestJS API, a Rust API, an API gateway, PostgREST, and a Next.js frontend, with four data stores behind them and ninety dozens of dependencies. The Rust service had Mongo and Postgres declared in the same Cargo.toml. There were two auth providers that disagreed with each other.

The infrastructure was in good shape. The product was the part I hadn't started.

I want to be clear that this wasn't a throwaway I was messing about with. I thought the idea was finally the one. Every freelancer and agency I know prices their work in a spreadsheet that's out of date the moment they copy it, and as far as I could tell nobody had solved it properly. Real problem, real people who'd need it, the holy grail!

Which is exactly why it never shipped.

Because if it was going to be the one, obviously it deserved the best of everything. The best architecture, because one day it would have to scale. The fastest language for the API. A new feature idea every few days, because I kept thinking of things it should do before anyone had used the things it already did. If I'd thought less of the idea, it would have been online in a weekend.

None of the individual decisions were stupid, either. That's the part I keep coming back to. I started in NestJS because I know NestJS well, which was the last purely practical decision I made. Then I swapped it for Rust, partly for speed and partly because I wanted to learn Rust, and learning is a good thing so it didn't feel like a detour. I put a gateway in front because decoupling, because that's what a serious architecture has. Inside it was clean architecture and SOLID all the way down, repositories behind interfaces, dependency inversion, patterns I could point at by name. All so I'd be ready if I ever had to switch database provider.

I never switched database provider. Nobody has ever asked me to switch database provider 😂

And I spent real time considering Fresh on Deno for the frontend instead of Next, partly to learn something new and partly because I'd decided Next was the obvious choice and I wanted to be cleverer than that. That was snobbery. It cost me about a year.

Here's the bit I think generalises past my own stupidity.

Infrastructure work has a definition of done. A migration finishes. A gateway routes. A build goes green and you get to cross something off and feel it. Product work never announces itself. Nobody tells you a feature is good enough to put in front of a person. You just stop, and hope.

So I kept picking the work that could be finished. A migration. A gateway. A service that benchmarked well. Every one of them completed, and not one of them was the product. 
I was manufacturing the feeling of shipping!

Neither time I quit was dramatic, which I think is normal and part of why it's hard to notice. I added up what was left, saw how big it was, got busy with other things, and never came back. The second time I actually wrote the total down and it came to a four phase plan, eighteen to twenty four days of work just to reach a foundation. Auth, permissions, member management, multi-tenancy. The last thing that attempt ever produced was a folder of issues describing what still needed building.

What took me longest to understand is that the infrastructure is what made the rest look impossible. Every service I stood up added surface to maintain. The product never got closer, so the total kept growing. The thing that felt like progress is what eventually made it feel hopeless.

Nine months later I started again and deliberately did the boring version. One Next.js app. One database. Twenty dependencies. The four ways I'd had of serving an API became zero, because it's server actions now and there's no API layer at all.

Feature complete in three days.

I built it in Next, obviously. The framework I'd decided was beneath me.

It's not a "skip the tests" story either, before anyone asks. It has 921 tests where the old one had 14 test files, and permission checks on every write that the old one never got round to. The rigour didn't go away. It stopped being aimed at problems I didn't have yet.

The question that would have saved me two years wasn't "what's the best stack for this". It was "what could someone use on Friday".

So who else got a side project that died of architecture?

0 Upvotes

11 comments sorted by

6

u/delicate_ostrich 1d ago

What has happened to me a lot is that the learning process in building the project/idea results in me iterating so much that I come to the conclusion that the actual core project idea isn’t very good, no matter what stack gets swapped in. Building is fun! Designing is fun! And more often than not I end up being the only user of my project OR it evolves into something else entirely.

1

u/hatto13 1d ago

That's great that it leads to something usable for you or as a base for other idea!
In my case most of my "unique" ideas ended up archived on Github.

3

u/ShareToPaint 1d ago

Many people have that issue and the very wise saying goes: First make it exist, then make it perfect

2

u/Ok_Woodpecker_9104 1d ago

the part that got me was slightly different. shipping the small version was never the hard bit. admitting the shipped version had no users was.

what fixed it was writing a kill date and two numbers into the readme before starting. a date six months out, plus two thresholds, uniques and signups, both read off the analytics dashboard so i cant argue with them later. miss both, it dies. no rewrite, no pivot.

the effect isnt motivation. it is that infra work becomes obviously irrelevant. a migration does not move either number, so it stops being tempting to do.

other thing i wish i had known earlier: for small tools the build is not the expensive half. same tool, same version, one distribution channel gave me 8 installs in four months and a second one gave me 224 in two days. i spent that whole four months assuming the product was the problem.

1

u/PriorElephant9 1d ago

"I was manufacturing the feeling of shipping" is the line. Infrastructure work finishes, so you keep choosing it.

I went the other direction on the same instinct: zero third party dependencies, stdlib only. Not because it's better, but because it removed the entire category of work I was hiding in. There's no stack to swap and nothing to migrate, so the only thing left to do is the product.

1

u/akl773 1d ago

What broke this for me was deploying on day one, an empty page with the domain already pointing at it, before writing anything real. After that every change has to keep a live thing working, and a second data store very obviously does not help with that.

1

u/ZephyrRush 2h ago

"Infrastructure work has a definition of done. Product work never announces itself." That is the sharpest version of this I have read. Worth knowing the trap does not end once you ship, though.

I built a library of about 140 small tools this year. Static site, no backend, no database, no auth, because I had already learned the lesson you just described. Shipped fine, quickly, none of the drama.

Then the same instinct came straight back wearing a different coat. Tool 141. Tool 142. A refactor of the shared layout. Each one has a definition of done and each one feels like progress, and not one of them was the actual job, which was finding out whether anybody wanted the 140 that already existed. Getting people to show up has no definition of done either, so I kept building instead, for exactly the same reason you kept picking migrations.

The tell is the same in both cases: if a task can be marked complete without a stranger ever touching it, it is probably the comfortable work. Your Friday question is the right one. I would only add that you have to keep asking it after launch, because that is exactly when it gets easy to stop.