A founder asked us last week why we hadn't suggested using a brand-new framework he'd seen on Hacker News. He was a little disappointed. He'd been hoping we'd recommend something cutting-edge, something that would feel like he was building on the future. Instead, we pitched him Next.js, Django, and Postgres — the same stack we've been using for years.
He almost picked a different agency over it. Then he hired us, we shipped his MVP in 7 weeks, and three months later he told me the boring choice was the best technical decision he'd made.
This is the case for boring technology when you're building an MVP — and what our actual stack looks like, with honest reasoning for every choice. If you're a founder evaluating quotes from agencies, this is also a useful filter: agencies that recommend trendy tech for startup MVPs are usually solving for their own learning curve, not your launch date.
Why "boring" wins for startups
Boring technology is technology that's been used in production at scale, by lots of teams, for long enough that the failure modes are understood. It's technology where Stack Overflow has answers to your weird edge cases. It's technology where hiring an engineer who can maintain it doesn't require a six-month search.
Trendy technology is the opposite. It's exciting because it solves an old problem in a new way. It's also exciting because nobody knows what'll break it yet.
For an MVP, you have one job: ship a working product to real users in 6-10 weeks. Every minute spent debugging a framework's edge cases, hunting for documentation, or being the first team to hit a bug is a minute not spent learning what your users actually want. Boring stacks let you spend that time on the thing that matters: your product.
The exception: if your product is the new technology — you're an AI infrastructure company, a database startup, a developer-tools company — then you have a real reason to use the new thing. For everyone else, the new thing is overhead pretending to be progress.
Now to the actual stack.
Frontend: Next.js, with React as the default
We default to Next.js for almost every web frontend we ship. That's not because it's the latest framework — it's because it's the most boring framework that does what we need.
What Next.js gives you:
- Server-side rendering out of the box. Your pages load fast, search engines index them properly, and you don't have to wire up SSR yourself.
- File-based routing that any new engineer can read in five minutes. No Webpack configs to maintain, no esoteric routing libraries.
- Image optimization, font loading, and asset handling that just works. You don't think about it.
- A massive ecosystem. Every third-party tool has Next.js examples. Every authentication provider has a Next.js SDK.
We use Vue or Angular when the client has a strong existing reason — there's an in-house team that already knows the framework, or there's a legacy codebase to integrate with. We don't use either as a default for greenfield startup work.
What we don't use, and why:
- Solid, Svelte, Qwik, Astro: Genuinely interesting, sometimes faster on benchmarks. But the ecosystem is smaller, hiring is harder, and the marginal performance win doesn't matter for an MVP.
- Frameworks released in the last 12 months: Wait. If they're still around in two years, we'll evaluate them.
- Heavy frontend frameworks like Nuxt for non-Vue projects: Adds complexity that most MVPs don't need.
Backend: Django or Node.js, depending on the team
This is where we do split, because it depends on context.
Django is our default when the client's product is data-heavy, has complex business logic, or needs an admin panel quickly. Django's ORM is mature, its admin interface saves weeks of work for internal tools, and Python is easier to hire for in most markets. We use Django REST Framework for the API layer. It's been the right choice for at least 80% of the SaaS, marketplace, and B2B tools we've shipped.
Node.js (with Express or Fastify) is the right choice when the team is JavaScript-focused (so they can move between frontend and backend), when real-time features are core to the product (Socket.io, server-sent events), or when the API has high request volumes that benefit from Node's event loop.
What we don't reach for:
- Rust, Go, Elixir for backends: Beautiful languages, often the right choice at scale. Almost never the right choice for an MVP. Hiring is harder, the ecosystem for product features (Stripe SDKs, auth providers, payment processors) is thinner, and the development speed is slower for the same scope.
- Serverless-first architectures (Lambda, Cloudflare Workers): Useful for specific workloads, painful as a primary backend. Cold starts hurt UX, debugging is harder, and most MVPs don't have the request patterns that benefit from serverless economics.
- Microservices on day one: A single Django or Node app is the right architecture for an MVP. You break it into services later, when you have a real reason. Pre-emptive microservices is the most common form of premature optimization we see.
Database: Postgres, almost always
Postgres is the right default for 95% of products. It's robust, it scales further than most startups will ever reach, it has JSON support when you need it, and it has every extension you might need (full-text search, vectors via pgvector, time-series via TimescaleDB).
We use SQLite for tiny internal tools and prototypes. We use Redis for caching, queues, and session storage. We use a vector DB (Pinecone or pgvector) when the product has RAG or semantic search.
What we avoid as defaults:
- MongoDB: Useful for specific document-heavy workloads. Painful as a primary database for the relational data most products actually have. The "schema-less" promise hides real schema problems that surface at the worst time.
- Firebase Realtime Database / Firestore: Fine for very simple apps with no relational logic. Fast to ship, expensive at scale, and very hard to migrate away from once you commit.
- Brand-new databases (anything launched in the last 18 months): Wait. We've watched too many of them get acquired, pivot, or die.
Mobile: React Native
For mobile, we default to React Native. Same reasoning as Next.js — it's the boring, proven choice for the cross-platform problem that 90% of startups actually have.
React Native gives you:
- One codebase for iOS and Android, sharing 80–90% of the code in practice.
- Native performance for the things users care about (scrolling, animations, navigation), with the option to drop into native modules when something specifically needs it.
- A mature ecosystem of libraries for camera, GPS, push notifications, in-app purchases, biometrics, and everything else you'll eventually need.
- The ability to hire from a much larger talent pool than you'd have for native iOS or Android specialists.
We use Flutter occasionally — usually when the team has Flutter experience or when the design system is complex enough that Flutter's widget control matters. We use native iOS or Android only when the product is genuinely platform-specific (e.g., a hardware-integration app, an Apple Watch companion app, a deeply customized Android launcher).
For most consumer or B2B mobile products, React Native is the default and it ships faster.
AI: Claude, OpenAI, LangChain — depending on the job
This part of our stack moves faster than the rest, but the principles still apply: pick the boring, proven option that fits the task.
For most LLM work, we use Claude via the Anthropic API. It's reliable on long-context reasoning, follows complex instructions consistently, and the safety profile fits production support agents. We use it for support automation, document processing, and most agent-style workflows.
We use OpenAI when the task benefits from GPT-4's structured-output mode, when the team is more familiar with the OpenAI ecosystem, or when cost optimization matters (GPT-3.5 / 4o-mini for high-volume, low-complexity tasks).
We use LangChain for orchestration when the workflow involves multiple steps, tool use, or RAG. We don't use it as a hammer — for single-shot prompt-completion tasks, the framework adds overhead without benefit.
For vector storage, pgvector if the project already has Postgres (which it usually does). Pinecone when the team doesn't want to operate vector search themselves and the volume justifies the cost.
What we don't reach for:
- Self-hosted open-source models as a default. There are real privacy and cost reasons to host models yourself, but the operational overhead is significant and the quality usually trails the frontier APIs by 6-12 months. We do it when the use case demands it, not as a starting position.
- AutoGen, CrewAI, and the new agent frameworks of the month. Some of these are genuinely useful. Most are solving problems that simpler architectures handle better. We use them when the workflow specifically requires multi-agent coordination, not by default.
Hosting and infra: Vercel, AWS, GCP
For most Next.js apps, we deploy to Vercel. It handles SSR, edge caching, and previews better than anything else. Cost scales linearly with traffic, but it's the right starting point.
For backend-heavy apps (Django, Node), we use AWS (ECS or EC2) or GCP (Cloud Run or GKE) depending on the client's existing relationships. Both work fine. We avoid bare-metal and self-managed Kubernetes clusters for MVPs — the operational overhead isn't worth it until you have a real reason.
For databases, managed Postgres (RDS, Cloud SQL, Supabase, Neon). Don't run your own database server. The hours you save on backups, replication, and patching are worth the slight cost premium.
For DNS and CDN, Cloudflare. For object storage, S3 or Cloud Storage. For monitoring, Sentry for errors and Vercel Analytics or PostHog for usage. None of this is exciting and all of it works.
What our default MVP stack actually looks like
For 80% of the MVPs we ship, the stack is:
| Layer | Choice |
|---|---|
| Frontend | Next.js (App Router), TypeScript, Tailwind CSS, shadcn/ui |
| Backend | Django + Django REST Framework (or Node.js + Fastify) |
| Database | Postgres (managed via RDS or Supabase) |
| Auth | Auth.js for Next-only apps, Django auth + JWT for full-stack |
| Payments | Stripe (Stripe Connect for marketplaces) |
| Mobile | React Native (when needed) |
| AI | Claude API + LangChain when relevant |
| Hosting | Vercel for Next, AWS/GCP for backend |
| Monitoring | Sentry, PostHog |
| CI/CD | GitHub Actions |
The whole stack costs roughly $50–$300/month to run for a startup at low traffic. None of it requires special expertise to maintain. All of it is documented, well-supported, and survives team changes.
When we deviate from the default
We do deviate. Here's when.
When the client has an existing team and codebase. If you're already running Vue, Laravel, and MySQL, we're not going to rebuild your stack to match our preference. We'll write Vue, Laravel, and MySQL with you. Continuity matters more than purity.
When the use case demands a specific tool. Real-time multiplayer needs WebSockets. Heavy ML inference might need a specialized model server. Geographic data wants PostGIS. We'll pick the right tool for the actual problem, not ignore it because it's not in our default stack.
When the founder is a strong technical operator with a different opinion. Sometimes a founder is an experienced engineer with a strong reason to use a specific stack. If their reasoning holds up, we'll work in their preferred stack. We push back when their reasoning is "I read about it on Hacker News last week."
How to evaluate a tech stack quote
If you're looking at proposals from multiple agencies, here are the questions worth asking each of them.
- "What's your default stack and why?" A good answer cites stability, hiring, ecosystem, and team familiarity. A bad answer cites recency or trendiness.
- "How long has your team been using this stack in production?" You want to hear "years," not "we just started."
- "What happens to my codebase if you stop being involved?" Can your team maintain it? Can another agency pick it up? If the answer is "only we can support this," that's a red flag.
- "Why not [more boring alternative]?" If they recommend something exotic, ask why not the proven option. A good answer is specific. A bad answer is vague.
Boring tech stacks aren't glamorous. They're not the kind of choice that gets you upvoted on Twitter. But they're the choice that gets your MVP shipped on time, maintained reliably, and handed off cleanly when the time comes.
If you want to talk through what stack actually fits your product — boring or not — book a 30-minute call. We'll give you our honest read on the architecture, the trade-offs, and what's worth caring about.
The goal is not to use the most interesting technology. The goal is to ship the most interesting product. Those are very different things, and confusing them is one of the most expensive mistakes you can make in your first 12 months.