Every software project starts with stack decisions. Programming language. Frontend framework. Backend framework. Database. Hosting. Build tools. Testing approach. Deployment pipeline. By the end of the first month, the team has made 10-20 decisions that will be very expensive to reverse later.
The decisions that matter most aren’t usually the ones engineers debate the most. Engineers debate React vs Vue vs Svelte while ignoring the more consequential choice of whether to use serverless or traditional hosting. The framework below helps make the high-stakes decisions well, and stop overthinking the low-stakes ones.
The decisions ranked by reversibility
The high-stakes decisions (very expensive to reverse, choose carefully):
- Programming language for the backend (5-year decision)
- Database engine (5-year decision)
- Hosting model (serverless vs container vs traditional - 3-year decision)
- Authentication approach (3-year decision)
- Multi-tenancy architecture (5-year decision)
The medium-stakes decisions (expensive but recoverable):
- Frontend framework (2-3 year decision)
- Build tools and bundlers (1-2 year decision)
- CSS framework or methodology (2 year decision)
- State management approach (2 year decision)
- API design (REST vs GraphQL vs RPC) (2-3 year decision)
The low-stakes decisions (changeable as needed):
- Specific UI component libraries (annual)
- Testing tools and approach (annual)
- Code formatting and linting (anytime)
- CI/CD pipeline tooling (anytime)
- Monitoring and logging tools (anytime)
Most teams spend too much time on items 11-15 (low stakes, lots of opinions) and not enough on items 1-5 (high stakes, fewer opinions). The framework below focuses on the high-stakes ones.
Programming language for the backend
The backend language defines your hiring pool, library ecosystem, and engineering culture for the life of the product.
The choices that make sense in 2026:
- TypeScript/Node.js: largest hiring pool, especially in US and LatAm. Mature ecosystem. Sometimes performance ceiling at high scale.
- Python: best for AI/ML-adjacent products. Strong web ecosystem (Django, FastAPI). Slower than alternatives but rarely the bottleneck.
- Go: best for high-performance services and CLI tools. Smaller hiring pool but quality is high. Excellent for backend infrastructure.
- Rust: best for performance-critical components. Steep learning curve. Smaller hiring pool. Use selectively.
- Java/Kotlin: best for enterprise-scale products with existing JVM infrastructure. Mature but heavy.
- C#/.NET: best for Windows-heavy enterprise environments and Microsoft-aligned shops.
The choices that rarely make sense for new projects:
- PHP: still works but smaller hiring pool, no clear advantages over alternatives for new projects.
- Ruby/Rails: still works but ecosystem shrinking, hiring harder than it was.
The honest recommendation:
For most US small-to-mid-size company products in 2026, TypeScript/Node.js is the default that works. The hiring pool is largest, the ecosystem is mature, and the performance is sufficient for most use cases. Choose something else only if you have a specific reason (AI/ML → Python, high-performance services → Go, enterprise integration → Java/.NET).
Database engine
The database is the longest-lasting decision in the stack. Migrations are possible but painful at scale.
The choices that make sense in 2026:
- PostgreSQL: the default. Handles relational data, JSON columns, full-text search, geospatial, vector embeddings (with pgvector). Mature, reliable, scales further than most teams need. Recommended for 80%+ of new projects.
- MySQL/MariaDB: still works. Slightly easier to host, slightly fewer features than PostgreSQL. Choose if you have specific reasons.
- SQLite: surprisingly good choice for small-to-medium projects and embedded use cases. Limitations are real but smaller than developers assume.
- MongoDB: choose only if your data is genuinely document-shaped and your queries match document patterns. Most teams that chose Mongo would have been better off with PostgreSQL JSON columns.
- Specialized databases (Redis for caching, Elasticsearch for search, ClickHouse for analytics): use as supplements to PostgreSQL, not replacements.
The honest recommendation:
PostgreSQL for almost everything. The cases where you need something else are rare and obvious. Don’t choose MongoDB or DynamoDB because they sound modern. Most “NoSQL is better at scale” arguments don’t apply at the scales most US small/mid-size company products operate at.
Hosting model
The hosting model affects deployment complexity, cost at scale, and operational burden.
The choices that make sense in 2026:
- Platform-as-a-Service (Vercel, Netlify, Railway, Render, Fly.io): minimum operational overhead, scales to most needs, predictable pricing. Default for most new projects.
- Container-based (Kubernetes, ECS, Cloud Run): more control, more complexity, justified at larger scale or specific compliance needs.
- Serverless functions (Vercel Functions, AWS Lambda, Cloudflare Workers): best for spiky workloads and edge compute. Cost-effective at small scale, can get expensive at high scale.
- Traditional VPS hosting (Hetzner, DigitalOcean droplets, AWS EC2): cheapest per-unit, highest operational burden. Worth considering if engineering team has DevOps capability.
- Edge runtimes (Cloudflare Workers, Vercel Edge): excellent for global products with low-latency requirements. Limitations on what you can run.
The honest recommendation:
Start with PaaS (Vercel, Render, Railway) for the application, and a managed database (Neon, Supabase, AWS RDS). This gets you to 90% of needs with 10% of the operational complexity. Migrate to containers if scale or compliance demands it later.
The mistake we see most often: choosing Kubernetes for a team that hasn’t proven product-market fit yet. The operational overhead of Kubernetes kills small teams faster than it helps them scale.
Authentication approach
Authentication is one of the highest-stakes infrastructure decisions because user accounts and sessions tie deeply into the product.
The choices that make sense in 2026:
- Hosted auth services (Auth0, Clerk, Supabase Auth, AWS Cognito): ship faster, handle edge cases (MFA, social login, enterprise SSO) without custom code. Best default for most new products.
- Open source auth libraries (NextAuth/Auth.js, better-auth, lucia-auth): more control, lower long-term cost, more implementation work upfront.
- Custom authentication: only when you have specific requirements (very unusual user models, strict data residency, deep integration with custom identity provider).
The honest recommendation:
Hosted auth (Clerk or Auth0 for most cases, Supabase Auth if you’re already on Supabase) for the first 12-18 months. Migrate to open source or custom only if pricing becomes prohibitive at scale or you hit specific limitations.
The mistake we see most often: building custom authentication “because it’s simple” and then spending years patching edge cases that hosted auth handles out of the box.
Multi-tenancy architecture
For SaaS products, multi-tenancy is a foundational decision that affects everything downstream.
The choices that make sense in 2026:
- Single database, shared tables with tenant_id column: simplest, lowest operational complexity, default for most SaaS. Limitations only matter at very high scale or strict data isolation requirements.
- Single database, schema per tenant: more isolation, more operational complexity, justified for some compliance use cases.
- Database per tenant: maximum isolation, significantly more operational complexity, justified for enterprise customers with data residency requirements or very high per-tenant volumes.
The honest recommendation:
Shared tables with tenant_id for almost all SaaS products. Migrate to more isolation only if specific enterprise customers require it (and charge them accordingly).
Frontend framework
The frontend framework decision is medium-stakes because frontend code is more replaceable than backend.
The choices that make sense in 2026:
- Next.js (React): largest hiring pool, mature ecosystem, handles SSR/SSG/CSR. Default for most projects.
- SvelteKit: better developer experience, smaller hiring pool, newer ecosystem. Good choice for teams that value DX.
- Astro: best for content-heavy sites with islands of interactivity. Excellent performance defaults.
- Remix (React): more opinionated than Next.js, fewer downsides, smaller ecosystem.
- Plain HTML/CSS/HTMX: surprisingly good for traditional CRUD apps. Less complex than the JS framework alternatives.
The honest recommendation:
Next.js for most products. SvelteKit if your team prefers it and you don’t need the broadest hiring pool. Astro for content sites. Plain HTML/HTMX for simple CRUD where the modern JS approach is overkill.
The stacks we recommend most often
For US small-to-mid-size company products in 2026, the stacks we recommend most often:
Standard SaaS product:
- Next.js (TypeScript) frontend and API routes
- PostgreSQL (Neon or Supabase) database
- Clerk or Supabase Auth
- Stripe for payments
- Vercel for hosting
- Resend for transactional email
Content-heavy product:
- Astro frontend
- PostgreSQL or SQLite database
- Cloudflare Pages or Vercel hosting
- Sanity or Contentful for CMS (or markdown files)
High-performance backend service:
- Go backend
- PostgreSQL database
- Container hosting (Fly.io or Cloud Run)
- gRPC or REST API
- Frontend as separate React or Svelte SPA
AI/ML-adjacent product:
- Python backend (FastAPI)
- PostgreSQL + pgvector
- Modal or similar for ML workloads
- React frontend
- Cloud Run or Railway hosting
These aren’t the only good answers. They are the answers that have worked across the most projects we’ve consulted on.
The decisions to overthink and the ones to underthink
The decisions worth spending real time on:
- Backend language (5-year commitment)
- Database engine (5-year commitment)
- Multi-tenancy architecture (defines the data model)
- Authentication approach (deep integration with everything)
The decisions to make quickly and move on:
- Specific UI component library (changeable in a sprint)
- Testing framework (changeable as the team evolves)
- Code formatter and linter (Prettier + ESLint, move on)
- State management library within React (debate over)
The decisions to revisit annually:
- Hosting provider (pricing and capabilities shift)
- Specific monitoring and observability tools (the space evolves quickly)
- Deployment pipeline (improvements available regularly)
The mistakes we see most often
The stack mistakes that hurt teams most:
- Choosing technologies the team doesn’t know. A new framework on a 90-day timeline is asking to slip the timeline.
- Microservices before product-market fit. The operational overhead kills the team’s velocity.
- MongoDB when PostgreSQL would work. Most “we need NoSQL” arguments don’t survive scrutiny.
- Custom authentication when hosted would work. Authentication is one of the highest-leverage hosted services available.
- Kubernetes without DevOps capability. Choose PaaS until scale forces the migration.
- Custom CSS framework when Tailwind would work. The marginal benefits don’t justify the maintenance cost.
- Polyglot stacks for premature optimization. Stick to one language until you have a specific reason to add another.
Most stack mistakes are about over-engineering. The teams that ship fast and scale well tend to start with boring, proven choices and only deviate when they have specific reasons.
The five-year question
When making any stack decision, ask: “If we have to live with this for five years, will we still be happy with the choice?”
- Will we still be able to hire developers for this technology?
- Will the ecosystem still be healthy and improving?
- Will scaling this be feasible without a rewrite?
- Will we be able to integrate with the systems we’ll need to integrate with?
- Will we be embarrassed about the choice or proud of it?
The answers should be confident yes for the high-stakes decisions. If you’re not sure, the choice probably isn’t right yet.
The tech stack decision is consequential. Made well, it accelerates the team for years. Made poorly, it creates technical debt that compounds with every feature. Worth taking the time to make well.