← All posts
January 20, 20266 min readFeedbackIQ team

Picking the stack for a solo-founder SaaS that needs to scale

Next.js 16 with Turbopack, Prisma on Neon, Clerk, Vercel AI Gateway, Resend. Why each, and what I deliberately did not pick.

Picking the stack for a solo-founder SaaS that needs to scale

Every new SaaS has the same opening gambit: two weeks of stack debate disguised as productivity. I wanted to avoid that. The rule I set for myself was “pick the boring option you’ve shipped before, unless a newer option is clearly better on a dimension that matters for this product.” Here’s the stack FeedbackIQ ended up with, and what I consciously didn’t pick.

Next.js 16 with Turbopack

I use Next.js for marketing pages, dashboards, and API routes in almost every project. The App Router handles the three main surfaces cleanly: static marketing (/, /vs/*, /blog/*), authenticated app (/dashboard/*), and programmatic endpoints (/api/*). Turbopack made the dev loop ~3× faster than webpack, and the stable release in 16 removed the last reason to hold out.

I did not use Remix or Astro. Remix’s data-loading model is elegant but I already have muscle memory for App RoutersearchParams and server components. Astro is beautiful for content sites but I needed a proper app shell, and the split would’ve been a second surface to maintain.

Prisma on Neon

Postgres was never in question — I need ordered writes, transactions, real constraints, and later pgvector for dedupe. Neon was the serverless Postgres I already had credits on, and it lets you toggle the vector extension with one checkbox in the dashboard. Prisma 7 added the postgresqlExtensions preview, which lets you declare extensions in the schema file:

datasource db {
  provider   = "postgresql"
  schemas    = ["feedbackiq"]
  extensions = [vector]
}

I briefly considered Drizzle. Drizzle has a cleaner migration story and its TypeScript types are better. But Prisma’s introspection plus its $queryRaw escape hatch (which I use for the pgvector cosine query) is a shorter path for a one-engineer team, and I’ve debugged Prisma perf issues before so I know what I’m walking into.

Clerk for auth

Clerk is the least interesting choice on paper and the highest-ROI one in practice. Email + GitHub OAuth + organizations + the UI is already built, the middleware is one import, and the dashboard handles the stuff I will 100% forget (email verification, password reset, session rotation). I spent about two hours on auth total, which for a side-project-that-is-also-a-SaaS is exactly the budget.

I did not roll my own with next-auth. Last time I tried that I spent a weekend debugging a refresh token loop. Never again until I have a team.

Vercel for hosting and AI Gateway

Deploy-on-push to main is the correct default. I pay for Vercel Pro, and the AI Gateway (in the same account) gives meopenai/* and anthropic/* routing with $5 of free credits, zero-config VERCEL_OIDC_TOKEN auth on production, and actual observability per model. It removed the need to carry OpenAI keys around.

I looked at Railway and Render. Both are great for Go/Rust/Python. For Next.js on the edge, Vercel is still the shortest path from git push to a working URL.

Resend for email

Upvote notifications and changelog digests go through Resend. Their API is boring in the best way: one POST, one promise, one event webhook for bounces. I used to use SendGrid and spent too many evenings fighting their dashboard. Resend replaces that entire category of pain.

What’s not on the list yet

No Redis, no queue, no separate worker. Every async path is either a Vercel function running past the response (fire-and-forget) .catch(err => console.error(...)) or a webhook from the GitHub App. I’ll add a queue when the dedupe pipeline starts ingesting Sentry + support tickets at volume. Until then it would be over-engineering.

Next post: the widget. One script tag, no framework, Shadow DOM so we don’t leak styles into the host site. It’s the smallest piece of code and the most-scrutinized-at-3am piece of code, because a broken widget is a visible outage.

Try FeedbackIQ

Drop a widget on your site, ship PRs from feedback

Claude reads the report, writes the fix, opens the PR on your repo. Dedupe with pgvector so the backlog doesn’t drown in duplicates.

Start for free