DEV Community

Cover image for How to choose a tech stack for your startup
Doktouri
Doktouri

Posted on • Originally published at agency.doktouri.com

How to choose a tech stack for your startup

Choosing a tech stack is one of the few early decisions you'll live with for years, yet founders often make it by copying whatever a popular blog post recommended last month. The right stack isn't the newest one — it's the one your team can ship in, hire for, and still be productive with after the honeymoon ends. A stack is a set of bets about your future: how fast you'll grow, who you'll hire, what your product becomes. Get the bets roughly right and the code almost writes itself. Get them wrong and you spend your second year fighting the decisions of your first. Here's the framework we actually use.

Start with the team you have

The single biggest predictor of velocity is whether your engineers already know the stack. A senior team that's fast in TypeScript and PostgreSQL will out-ship a team fumbling through an unfamiliar "better" language every time. Familiarity compounds: it's not just syntax, it's knowing the debugger, the testing patterns, the deployment quirks, the libraries that are actually good versus the ones with great READMEs and abandoned issue trackers. Optimize for the tools your people are dangerous in today, not the ones you'd pick in a vacuum.

If you're hiring soon, factor in the labor market. A stack with a deep talent pool — TypeScript, Python, React — means you can staff up quickly and cover for a departure without a crisis. An exotic choice (Elixir, Rust on the web, a niche framework) narrows your funnel to a handful of specialists who cost more, take longer to find, and are harder to replace when one leaves. That's a fine trade if the technology is genuinely core to your product's value. It's a terrible trade if you picked it because it was interesting.

There's a subtler cost too: onboarding. A new hire on a mainstream stack is productive in days. On an unusual one, weeks. Multiply that across every engineer you'll ever add and the "boring" choice quietly wins on total cost.

Match the stack to the problem, not the trend

Ask what your product actually needs before reaching for anything fancy:

  • Data-heavy and relational? A boring, reliable PostgreSQL database will take you further than any trendy alternative. It does JSON, full-text search, geospatial queries, and transactional integrity in one engine — see PostgreSQL for startups for why it's the default we reach for.
  • Real-time or collaborative? Look at Supabase for managed real-time subscriptions, or plan a websocket layer early rather than bolting one on later. Our realtime features architecture guide covers the patterns.
  • Content-driven web app? Next.js with server-side rendering gives you SEO without a separate CMS. If organic traffic matters, read why server-side rendering still wins for SEO before you commit to a client-only SPA.
  • Standard CRUD API? A NestJS service on Node keeps structure without ceremony, and it shares a language with your front end so context-switching is cheap.
  • AI or search features? You'll want vector storage. Postgres with the pgvector extension covers most needs before you reach for a dedicated vector database.

Most products are more ordinary than their founders think. The novelty lives in the product idea and the go-to-market, not in the plumbing. Ordinary problems deserve proven tools.

Favor boring, well-supported technology

For an early-stage company, boring is a feature. Mature technologies have documentation, Stack Overflow answers, hardened libraries, LLM training data (your AI pair-programmer is far more useful on a popular stack), and known failure modes. Bleeding-edge tools have GitHub issues and a Discord where the maintainer promises a fix "soon."

The test we apply: has someone already hit the problem you're about to hit, and written it down? With Postgres, React, or Node, the answer is almost always yes. With a two-year-old framework, you're the QA team. Reserve your innovation budget — and every team has a limited one — for the product itself. Every unusual infrastructure choice is a tax you pay on every future hire, every debugging session, and every 2 a.m. incident when the one person who understood it is asleep or gone.

This isn't an argument against ever adopting new tools. It's an argument for spending your novelty where it earns its keep. Pick one thing to be adventurous about, if you must, and make everything around it dependable.

The build-vs-buy default

A modern stack is as much about what you don't build. Auth, email delivery, payments, file storage, background jobs, error tracking — every one of these is a solved problem you can rent. Managed services (Supabase, Clerk, Stripe, Resend, Sentry) cost real money at scale, but at the stage where you're choosing a stack, engineering time is far more expensive than a SaaS invoice. Build the thing that's yours; buy the thing that's everyone's. You can always bring a service in-house later once it's a proven cost center — that's a good problem to have.

Design for two years, not two months

The trap sits on both ends. Kubernetes and microservices for a pre-launch product is premature complexity: you inherit the operational burden of a company ten times your size while serving zero users. But a stack that physically can't grow — a database that won't scale, a no-code tool you'll have to rip out at 10,000 users, a framework with a hard ceiling — is a false economy that mortgages your future for a fast start.

The sweet spot is a modular monolith on managed hosting: a single deployable app with clean internal boundaries, simple enough to move fast now, structured enough to split apart later if you genuinely need to. You almost never need to decide microservices vs monolith on day one — and if you're tempted, our microservices vs monolith breakdown will probably talk you out of it. Draw module lines where your domains actually separate (billing, users, the core product), keep them talking through well-defined interfaces, and you'll have the option to extract a service the day the traffic justifies it — not before.

A worked example: the default stack we reach for

To make this concrete, here's the stack we hand most early-stage web products, and the reasoning behind each choice — not because it's universally correct, but because it's a defensible default you'd need a specific reason to deviate from:

  • TypeScript everywhere. One language across front end, back end, and shared validation. Types catch a whole class of bugs before runtime and make refactoring safe, which matters most exactly when you're changing things fastest.
  • Next.js for the web front end. Server rendering for SEO, a mature ecosystem, and a hosting story that's a git push. If you're weighing it against plain React, Next.js vs React lays out when the extra framework earns its keep.
  • PostgreSQL for data. Relational integrity, JSON when you need flexibility, and it scales further than most startups ever test.
  • Supabase or a NestJS API for the backend. Managed auth, storage, and real-time out of the box, or a structured Node API when you need more control. Compare the managed options in Supabase vs Firebase.
  • Managed hosting, one deployable app. No Kubernetes, no service mesh, no ops team you don't have.

This stack has a deep talent pool, excellent documentation, strong AI-assistant support, and a clear upgrade path. That combination — not any single tool's cleverness — is what makes it a good bet. Deviate deliberately, for a reason you've written down, not by default.

Common mistakes we see

  • Resume-driven development. Choosing a technology because it's good for the engineer's career, not the product. It's an understandable instinct and a costly one.
  • Optimizing for a scale you don't have. Architecting for a million users while you're chasing your first hundred. The million-user rewrite is a luxury problem; ship first.
  • Fragmenting the language. A Go backend, a Python data layer, and a TypeScript front end means three ecosystems, three sets of tooling, three ways to be an expert. One language across the stack is a real force multiplier for a small team.
  • Ignoring the deployment story. A stack isn't just the code — it's how it gets to production. If you can't describe how you'll deploy, monitor, and roll back on day one, you haven't finished choosing.
  • Confusing TypeScript with optional. For anything non-trivial, type safety pays for itself fast. If you're on the fence, is TypeScript worth it makes the case.

Write the decision down

Whatever you choose, record why in a short document — an architecture decision record, even a single paragraph per major choice. Six months from now, someone will question a call, and "we picked Postgres because we needed transactional integrity and JSON in one database, and we were willing to trade horizontal-scale simplicity for it" is a far better answer than a shrug. Writing it down also forces you to actually have a reason, which catches the choices you were making on vibes.

A stack decision you can defend is a stack decision you can revisit deliberately instead of by accident. Circumstances change — a bet that was right at ten users can be wrong at ten thousand — and the teams that adapt gracefully are the ones who know which assumptions they were betting on in the first place.

We help founders make these calls without the hype every week — if you're staring at a blank architecture diagram, let's talk.


Originally published on the Doktouri Agency blog. We build web, mobile, SaaS, and AI products — let's talk.

Top comments (0)