HA
18 Jan 2025 3 min read Updated 9 Feb 2025

3 years as the only engineer at a startup

What I learned building two full EdTech platforms solo, from architecture decisions with no one to sanity check them to shipping on App Store and Play Store alone.

careerstartupengineering

Running product and engineering alone sounds clean from a distance. In practice it means every decision compounds because there is nobody coming behind you to cleanly split responsibility. The reward is speed. The cost is that you find out immediately whether your architecture, priorities, and instincts hold up when users arrive.

Table of contents

The real job was compression

At AfterBoards, the work was never just “build the feature.” The actual job was compressing the path from a product idea to a stable experience students could trust. That meant:

  • shipping the web app
  • shipping the mobile app
  • building the backend paths that powered both
  • keeping admin tools fast enough for the content team
  • deciding where AI belonged and where it absolutely did not

When a team is small, every abstraction has to pay rent. I became much stricter about introducing new infrastructure after seeing how quickly complexity becomes maintenance debt when the same person has to own it months later.

Architecture decisions feel louder when you are alone

The hardest part of solo engineering is not implementation volume. It is making architecture calls without a convenient feedback loop. A few patterns mattered a lot for me:

Shared language across surfaces

Using TypeScript across product surfaces reduced translation overhead. It kept frontend decisions closer to backend contracts and made it easier to move between features without burning time on context switching.

Product workflows first, frameworks second

I stopped evaluating tools in isolation. The more useful question became: does this help me ship a complete workflow faster next month? That lens is why I leaned toward Next.js, Server Actions, and a monorepo setup that kept related code near each other.

Make operational work visible

If a flow took the content team multiple days, it was not “ops,” it was a product problem. Once I framed it that way, the AI exam-generation pipeline was obvious work instead of side work.

Shipping on both app stores changes your tolerance for fragility

Web-only systems let you recover quickly. Mobile release cycles are less forgiving. That changed how I thought about authentication, versioning, and real-time features. I had to design flows that survived:

  • network interruptions
  • stale mobile clients
  • device-specific auth edge cases
  • payment state mismatches

This is where “full-stack” stops being a label and becomes operational responsibility.

What improved the most

The biggest personal shift was moving from feature thinking to system thinking. I became more deliberate about failure modes, more suspicious of overly clever abstractions, and much better at deciding what did not need to be built yet.

type ProductDecision = {
  speed: "now" | "later";
  operationalCost: number;
  userImpact: number;
};
 
export function shouldShip(decision: ProductDecision) {
  return decision.userImpact > decision.operationalCost || decision.speed === "now";
}

That is obviously simplified, but it reflects the mindset shift: every technical choice had to justify itself against user value and maintenance cost.

What I would keep doing

I would keep biasing toward:

  • end-to-end ownership
  • small, legible stacks
  • product-facing automation
  • systems that remove repeated human bottlenecks

Being the only engineer sharpened my standards because there was nowhere to hide weak decisions. That was difficult, but it was also the fastest way to learn what really holds up in production.

Written by

Himanshu Agarwal

Founding engineer based in Bengaluru, building product systems that connect web, mobile, backend, and AI without handoff gaps.

Keep reading

Related posts

Browse all posts

Discussion

Comments

Configure the `PUBLIC_GISCUS_*` environment variables to enable GitHub Discussions-powered comments here.