Every few months, someone asks us what stack we use. The answer has been remarkably stable — we've been building on the same core technologies for over two years now, with minor adjustments. Here's the full breakdown and the reasoning behind each choice.
Frontend: Next.js + React
Next.js gives us the best of both worlds: server-side rendering for SEO-critical pages and client-side interactivity where it matters. The App Router has matured significantly, and Server Components let us keep bundle sizes small without sacrificing developer experience.
We pair it with Tailwind CSS for styling. The utility-first approach eliminates naming debates, keeps styles co-located with markup, and produces smaller CSS bundles than any component library we've tried.
Backend: Node.js + TypeScript
TypeScript across the entire stack is a massive productivity win. Shared types between frontend and backend catch integration bugs at compile time, not in production. We use tRPC or simple REST depending on the project — tRPC for internal APIs, REST when the API needs to be consumed by third parties.
For the runtime, Node.js with Fastify handles most workloads efficiently. For CPU-intensive tasks, we offload to background workers.
Database: PostgreSQL
Postgres is the default. It handles relational data, JSON documents, full-text search, and even vector embeddings (with pgvector). We rarely need a second database.
We use Prisma as the ORM for most projects — it provides type-safe queries and handles migrations cleanly. For performance-critical queries, we drop down to raw SQL.
Payments: Stripe
Stripe is non-negotiable for SaaS billing. The API is well-designed, the documentation is excellent, and the ecosystem (Stripe Tax, Stripe Connect, Billing Portal) covers virtually every payment scenario we encounter.
We've built enough Stripe integrations to have strong opinions about webhook handling, idempotency, and subscription lifecycle management — which we covered in our Stripe billing post.
Infrastructure: Vercel + AWS
Vercel for the frontend — zero-config deployments, preview URLs for every PR, and edge caching that just works. For backend services that need more control, we use AWS with SST (Serverless Stack) for infrastructure-as-code.
This combo gives us fast iteration on the frontend while maintaining full control over backend infrastructure when we need it.
Why Stability Matters
We could chase every new framework. But stack stability means our team builds deep expertise, our boilerplate is battle-tested, and our estimates are accurate. New projects start fast because we're not learning tools — we're solving your business problems.
That said, we're not dogmatic. If your project genuinely needs something different (Python ML services, Go for high-concurrency, etc.), we adapt. The stack serves the product, not the other way around.