Skip to content

Chapter 20: Tech Stack Decisions

Choosing the right tools is less about picking the "best" technology and more about picking the best technology for your team, timeline, and target market.

Why This Matters

  • Owner: Your tech stack determines hiring pool size, development speed, infrastructure costs, and long-term maintainability. A poor choice here compounds over years.
  • Dev: You will build on this foundation daily. The stack shapes your productivity, debugging experience, and career trajectory on this project.
  • PM: Stack choices constrain feature velocity, third-party integrations, and what is feasible within a sprint. Understanding trade-offs helps you plan realistically.
  • Designer: Frontend framework choice affects what animations, interactions, and design system tools are available to you.

The Concept (Simple)

Choosing a tech stack is like choosing tools to build a house:

  • You could use premium tools and exotic materials, but if your crew only knows basic carpentry, the house will take forever.
  • The "best" hammer is the one your team can swing effectively.
  • Some tools lock you into a specific supplier (vendor lock-in). Others are interchangeable.

The goal is not to pick the trendiest stack. The goal is to pick the stack that lets your team ship reliable software fastest with the fewest regrets in 2-3 years.


How It Works (Detailed)

The SaaS Stack Layers

┌─────────────────────────────────────────────────────────┐
│                     PRESENTATION                         │
│    Frontend Framework  |  Mobile  |  Design System       │
├─────────────────────────────────────────────────────────┤
│                      API LAYER                           │
│       REST / GraphQL  |  API Gateway  |  WebSockets      │
├─────────────────────────────────────────────────────────┤
│                   APPLICATION                            │
│    Backend Framework  |  Auth  |  Business Logic         │
├─────────────────────────────────────────────────────────┤
│                     DATA LAYER                           │
│     Primary DB  |  Cache  |  Search  |  Queue            │
├─────────────────────────────────────────────────────────┤
│                   INFRASTRUCTURE                         │
│   Cloud Provider  |  CI/CD  |  Monitoring  |  CDN        │
└─────────────────────────────────────────────────────────┘

Frontend Framework Comparison

FrameworkLearning CurveEcosystemHiring PoolPerformanceBest For
ReactMediumMassiveLargestGoodComplex dashboards, SPAs
Next.jsMediumLargeLargeExcellentSEO + app hybrid, full-stack
VueLowGoodMediumGoodRapid prototyping, SMB apps
SvelteLowGrowingSmallExcellentPerformance-critical UIs
AngularHighLargeLargeGoodEnterprise, large teams
HTMXVery LowSmallSmallExcellentServer-rendered, simple UIs

Backend Framework Comparison

FrameworkLanguageHiring PoolPerformanceBest For
Express / FastifyNode.jsLargestGoodAPI-first, JS full-stack
DjangoPythonLargeModerateData-heavy, rapid prototyping
RailsRubyMediumModerateConvention-over-config, speed
Spring BootJava/KotlinLargeExcellentEnterprise, complex domains
LaravelPHPLargeGoodCRUD-heavy, content platforms
Go (net/http/Gin)GoMediumExcellentHigh-throughput microservices
ASP.NET CoreC#LargeExcellentEnterprise, Microsoft ecosystem
PhoenixElixirSmallExcellentReal-time, high-concurrency

Database Comparison

DatabaseTypeScalingBest For
PostgreSQLRelationalVertical+Default choice for most SaaS
MySQLRelationalVertical+Simpler relational needs, wide support
MongoDBDocumentHorizontalFlexible schemas, content-heavy apps
DynamoDBKey-ValueHorizontalAWS-native, predictable performance
RedisIn-memoryClusterCaching, sessions, real-time features
ElasticsearchSearchHorizontalFull-text search, log analytics
ClickHouseColumnarHorizontalAnalytics, event data, time-series

Common Stack Combinations

┌─────────────────────────────────────────────────────────────┐
│              POPULAR SAAS STACK COMBOS                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  "The Startup Default"          "The Enterprise Java"       │
│  ┌─────────────────────┐        ┌─────────────────────┐    │
│  │ Next.js (frontend)  │        │ React (frontend)    │    │
│  │ Node.js (backend)   │        │ Spring Boot (API)   │    │
│  │ PostgreSQL (DB)     │        │ PostgreSQL (DB)     │    │
│  │ Redis (cache)       │        │ Redis (cache)       │    │
│  │ Vercel / AWS (infra)│        │ AWS / GCP (infra)   │    │
│  └─────────────────────┘        └─────────────────────┘    │
│                                                             │
│  "The Rapid Prototype"          "The Data-Heavy SaaS"      │
│  ┌─────────────────────┐        ┌─────────────────────┐    │
│  │ Rails (full-stack)  │        │ React (frontend)    │    │
│  │ Hotwire (frontend)  │        │ Django / FastAPI     │    │
│  │ PostgreSQL (DB)     │        │ PostgreSQL (primary) │    │
│  │ Sidekiq (jobs)      │        │ ClickHouse (OLAP)   │    │
│  │ Heroku / Render     │        │ Redis (cache)       │    │
│  └─────────────────────┘        │ AWS (infra)         │    │
│                                 └─────────────────────┘    │
│                                                             │
│  "The Go Microservices"         "The Full TypeScript"      │
│  ┌─────────────────────┐        ┌─────────────────────┐    │
│  │ React (frontend)    │        │ Next.js (full-stack) │    │
│  │ Go (services)       │        │ tRPC (API layer)    │    │
│  │ PostgreSQL + Redis  │        │ Prisma (ORM)        │    │
│  │ Kafka (events)      │        │ PostgreSQL (DB)     │    │
│  │ Kubernetes (infra)  │        │ Vercel (infra)      │    │
│  └─────────────────────┘        └─────────────────────┘    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Tech Stack Decision Flowchart

START: What is your team's strongest language?

  ├── JavaScript/TypeScript ──▶ Next.js + Node.js + PostgreSQL
  │                              (Full-stack TypeScript)

  ├── Python ──▶ Is it data/ML heavy?
  │               ├── Yes ──▶ Django/FastAPI + PostgreSQL + ClickHouse
  │               └── No  ──▶ Django + PostgreSQL + Redis

  ├── Ruby ──▶ Rails + PostgreSQL + Sidekiq
  │             (Fastest time-to-MVP)

  ├── Java/Kotlin ──▶ Spring Boot + PostgreSQL + Redis
  │                    (Enterprise-grade from day one)

  ├── Go ──▶ Planning microservices early?
  │           ├── Yes ──▶ Go services + gRPC + PostgreSQL + Kafka
  │           └── No  ──▶ Consider Node.js or Rails instead

  └── C# ──▶ ASP.NET Core + SQL Server/PostgreSQL
              (Microsoft ecosystem)

THEN: Add infrastructure

  ├── Budget < $500/mo ──▶ Vercel / Render / Railway
  ├── Budget $500-5K/mo ──▶ AWS / GCP managed services
  └── Budget > $5K/mo   ──▶ AWS / GCP + Kubernetes (if team can manage it)

Build vs Buy Decision Matrix

Before building any infrastructure component, run it through this matrix:

ComponentBuildBuy / Use SaaSRecommendation
AuthenticationFull control, custom flowsAuth0, Clerk, Supabase AuthBuy (always)
Payments/BillingCustom pricing modelsStripe, Paddle, ChargebeeBuy (always)
Email sendingDeliverability controlSendGrid, Postmark, ResendBuy
SearchCustom ranking, tight integrationAlgolia, Typesense, MeilisearchBuy until scale
File storageN/AS3, Cloudflare R2, GCSBuy (always)
MonitoringCustom dashboardsDatadog, Grafana Cloud, New RelicBuy
Error trackingN/ASentry, BugsnagBuy (always)
Feature flagsSimple on/off onlyLaunchDarkly, Flagsmith, UnleashBuy or OSS
AnalyticsPrivacy-first, custom eventsAmplitude, Mixpanel, PostHogBuy or OSS
Core product logicYour competitive advantageN/ABuild (always)
Admin dashboardCustom workflowsRetool, Forest AdminDepends on stage
Background jobsTight integration neededInngest, TemporalBuild early, buy later
BUILD vs BUY Decision Tree:

Is this your core product differentiator?

  ├── YES ──▶ BUILD IT (this is your competitive moat)

  └── NO ──▶ Does a reliable SaaS/OSS solution exist?

              ├── YES ──▶ Can you afford it at 10x current scale?
              │            │
              │            ├── YES ──▶ BUY IT
              │            └── NO  ──▶ Buy now, plan migration later

              └── NO ──▶ Can you build it in < 2 weeks?

                          ├── YES ──▶ BUILD IT (keep it simple)
                          └── NO  ──▶ Find the closest solution + adapt

Vendor Lock-In Assessment

Rate each technology on a lock-in scale:

LOW LOCK-IN ◄──────────────────────────────────────► HIGH LOCK-IN

PostgreSQL          AWS Lambda          DynamoDB
Redis               Cloud Functions     Firebase Firestore
Kubernetes          Managed Kubernetes  Azure Cosmos DB
Docker              CloudFront          Vercel Edge Functions
OpenSearch          RDS                 AWS Amplify
Self-hosted tools   Managed Redis       Proprietary AI APIs
S3-compatible       SNS/SQS             Cloud Spanner

RULE: Keep your core data layer low lock-in.
      Accept higher lock-in for commodity infrastructure.

Lock-in mitigation strategies:

StrategyEffortEffectiveness
Use open-source databasesLowHigh
Containerize everythingMediumHigh
Abstract cloud SDK callsMediumMedium
Multi-cloud deploymentHighOverkill (usually)
Use Terraform/Pulumi for IaCMediumHigh

In Practice

Case Study: Choosing a Stack for a B2B Analytics SaaS

Context: 3-person founding team (2 devs, 1 designer). Target market: mid-market companies. Data-heavy product with dashboards.

Decision process:

  1. Team skills: Both devs know TypeScript and Python
  2. Product needs: Complex dashboards, real-time data, CSV imports
  3. Timeline: MVP in 3 months
  4. Budget: $300/month infrastructure

Stack chosen:

  • Frontend: Next.js (React expertise + SSR for landing pages)
  • Backend: FastAPI (Python, great for data processing)
  • Database: PostgreSQL (relational data) + ClickHouse (analytics queries)
  • Cache: Redis
  • Infra: Railway (simple, affordable, scales)
  • Auth: Clerk (buy, not build)
  • Payments: Stripe

Why it worked: Python excelled at data pipeline code. TypeScript handled the complex dashboard UI. They bought everything that was not their core product.

Common Mistakes

  1. Choosing Go or Rust for a CRUD SaaS -- you are optimizing for performance you will not need for years at the cost of development speed
  2. Using MongoDB as your primary database -- relational data (users, subscriptions, permissions) wants a relational database
  3. Building auth from scratch -- this wastes 2-4 weeks minimum and you will have security vulnerabilities
  4. Picking a stack based on blog posts -- choose based on your team's existing skills, not Hacker News trends
  5. Not considering the hiring market -- a niche language means fewer candidates and higher salaries

Key Takeaways

  • The best stack is the one your team already knows; switching costs are almost always underestimated
  • PostgreSQL is the correct default database for SaaS -- choose something else only with a specific reason
  • Buy every commodity component (auth, payments, email, monitoring); build only your core product differentiator
  • Vendor lock-in matters most at the data layer; accept lock-in for compute and edge infrastructure
  • Your stack will evolve; optimize for speed-to-MVP now, not theoretical scale in 3 years
  • Full TypeScript (Next.js + Node.js) is the highest-leverage choice for small teams in 2025-2026

Action Items

Owner

  • [ ] Audit your current team's language skills before making stack decisions
  • [ ] Set a monthly infrastructure budget ceiling for the first year
  • [ ] Ensure the chosen stack has a healthy hiring market in your geography or remote pool
  • [ ] Review the build vs buy matrix with your CTO -- every "build" decision delays your core product

Dev

  • [ ] Prototype your top 2 stack candidates with a weekend spike before committing
  • [ ] Set up the database schema with multi-tenancy from day one (see Chapter 19: SaaS Architecture 101)
  • [ ] Containerize your application early (Docker) to avoid lock-in and ease deployment (see Chapter 21: Shipping and Deployment)
  • [ ] Document your stack decisions and rationale in an ADR (Architecture Decision Record)

PM

  • [ ] Map your feature roadmap against stack capabilities -- flag anything that seems hard
  • [ ] Build integration requirements into your PRDs (what third-party services are needed?)
  • [ ] Understand which "buy" components have usage-based pricing that could spike with growth

Designer

  • [ ] Evaluate component libraries available for the chosen frontend framework
  • [ ] Set up a design system that maps to the UI framework (e.g., Tailwind + Radix for React)
  • [ ] Confirm that animation/interaction requirements are feasible in the chosen framework
  • [ ] Review accessibility tooling available in the stack

The Product Builder's Playbook