I've spent the last few years building products that didn't exist yet — early-stage AI and SaaS work where the repository is empty on Monday and someone is depending on it by the end of the quarter.
This is less a build log than a look back at what actually changed in how I work, because the shift from writing features to owning outcomes rearranged most of my assumptions.
The intern years: components and the value of being reusable
I started on frontend component libraries, REST endpoints, and internal tooling. The work was small in scope and I was slightly embarrassed by that at the time.
What I didn't see then: a well-built component library is leverage. The reusable components I standardized got used across four client projects, and the team moved faster for reasons nobody attributed to the components. Boring infrastructure that everyone builds on beats impressive work that only you touch.
I also learned to write automated regression scripts, mostly because I broke things and got tired of breaking them again.
Full-stack: the backend teaches you about limits
Next came core backend services — Postgres data modeling, Redis background jobs, React applications on top. Authenticated customer portals, batch importers, webhook delivery.
Two lessons landed hard here.
Queues are where systems actually fail. Cutting average background queue processing time by 45% wasn't clever algorithms; it was finding the jobs doing synchronous work that had no business being synchronous, and the ones re-fetching data they'd already loaded. Most performance work is removal.
Scale exposes modeling mistakes, not code mistakes. Pushing data import throughput past 100,000 customer records didn't break because the code was slow. It broke at the schema — the wrong indexes, the wrong normalization decision made months earlier when the table had fifty rows. You can rewrite a service in a weekend. You cannot casually rewrite a schema that production data already lives in.
Founding engineer: owning the whole thing
Then the scope became everything: architecture, API design, frontend state, AI agent workflows, deployment. Three products from empty repo to customers using them — a deal intelligence pipeline, an autonomous video pipeline, and a lead management CRM — plus the observability layer that made all of them debuggable.
Four things I believe more strongly now than when I started.
Ambiguity is the job, not an obstacle to it. Nobody hands a founding engineer a spec. The work is deciding what to build, and the engineers who wait for clarity wait forever.
Speed of learning beats hypothetical perfection. Every architecture decision I agonized over for a week in the abstract got settled in an hour by shipping something and watching it behave. The information you need is downstream of the thing you haven't built yet.
The boundary between your system and someone else's is where bugs live. CRM webhooks, Meta payloads, media codecs, broker headers — every one of my worst production incidents happened at a boundary I'd assumed was well-behaved. Assume every external system will send you malformed data twice.
Own the failure, not just the feature. Anyone can build the happy path. Being the person who's responsible when it's down at 11pm changes what you build: memory limits, dead-letter queues, idempotency keys, rollback paths. That's not defensive engineering, that's the actual product.
What I'm still working on
Knowing when a decision deserves the week of thought. "Just ship it" is right most of the time and catastrophically wrong for the small set of choices that are expensive to unwind — data models, auth boundaries, anything that writes to a system you don't control. I'm still calibrating which is which, and I suspect that calibration is most of what experience actually means.