Abhishek ChaudharyAbhishek Chaudhary

Two-Stack Posture: Hono + Bun Production, Next.js MVP

My production SaaS stack 2026 is Bun and Hono with Postgres; my MVP and personal-brand stack is Next.js 16 with SQLite. Here is why I run both.

Abhishek Chaudhary13 min read

The two-stack posture is the practice of running two distinct application stacks in parallel as a solo founder: a production SaaS stack sized for revenue-bearing apps with paying customers, and a separate MVP and personal-brand stack sized for content sites and quick experiments. My production stack in 2026 is Bun with Hono.js and Postgres; my MVP stack is Next.js 16 with SQLite. The two share five constants and split on the runtime, framework, and database. This post names the split layer by layer, then shows the failure mode of using one stack for both classes of work.

TL;DR

  • Two stacks, picked to the job class, not to my framework preference.
  • Production SaaS: Bun, Hono.js JSX SSR, Postgres, all on Drizzle.
  • MVP and personal brand: Node.js 24, Next.js 16 App Router, SQLite via better-sqlite3, also on Drizzle.
  • Constants strip across both: BetterAuth, Drizzle, Redis, Docker, Cloudflare.
  • Failure mode the split prevents: scaling Next.js + SQLite into a write-heavy multi-tenant SaaS, or reaching for Hono on a content site that lives or dies by metadata plumbing.

I have shipped software for 15+ years across ten-plus self-owned SaaS ventures, parallel enterprise consulting, and a small engineering team led on most of those products. The portfolio carries thousands of paying customers across the production apps today. This site, abhishekchaudhary.com, is the public artifact of the second stack: a personal brand, a 50+ track music catalogue, a blog, an admin panel. Different jobs, different tools. I have written about the MVP-side picks before, in my solo-founder AI stack post; this post is the layer-by-layer breakdown of why that is one of two stacks, not the only one.

Where the two stacks split, layer by layer

LayerProduction SaaSMVP and personal brand
RuntimeBunNode.js 24 (bookworm-slim)
FrameworkHono.js with JSX SSRNext.js 16 App Router, standalone
DatabasePostgresSQLite via better-sqlite3 (WAL)
ORMDrizzleDrizzle
AuthBetterAuthBetterAuth
Rate limitRedisRedis
ContainerDocker, self-hosted on HetznerDocker, self-hosted on Hetzner
EdgeCloudflare in frontCloudflare in front
Model APIGemini at scale, Claude internalOne key per app, swappable

The runtime, framework, and database split. Everything else stays constant. That row of constants is doing real work; I will name it explicitly below.

Hono on Bun for production: JSX SSR lets me handcraft every byte of markup my paying users and Googlebot see, including schema.org structured data baked into pages instead of bolted on via plugins. Bun shaves enough cold-start time that I can run a Hetzner VPS one tier smaller for the same load. Postgres takes over because the write pattern on a real SaaS, with concurrent customer writes, billing webhooks, background jobs, and multi-instance deployments, sails past SQLite's serialised-writer ceiling.

Next.js on Node.js 24 for the MVP and personal-brand stack is the inverse case. Here the job is SEO plumbing, metadata, sitemap, robots, OG images, JSON-LD, the markdown alternate per llmstxt.org, and a small admin panel for one operator. Next.js absorbs that work for free; Hono would require me to hand-roll every line of it.

The constants strip: BetterAuth, Drizzle, Redis, Docker, Cloudflare

Five layers stay the same across both stacks. I think of them as the constants strip, the band that lets the two stacks coexist on the same operator's workflow without context-switching tax.

  • BetterAuth does session and admin gating on both stacks. Same mental model, same DB adapter (Drizzle), same admin-plugin pattern. When I add auth to a new project, I do not relearn anything.
  • Drizzle ORM speaks both SQLite and Postgres with the same $inferSelect and $inferInsert types. Same schema file shape, same migration tool (drizzle-kit), same query API. When I prototype a feature on SQLite and ship it on Postgres, the code that touches the database barely moves.
  • Redis is the rate limiter on both stacks. Same INCR plus TTL idiom, same graceful-fallback policy when Redis is down.
  • Docker with docker compose up -d --build is the deploy on both stacks. One file, one command, one box. No Vercel, no Render, no per-MAU SaaS tax on the platform layer.
  • Cloudflare sits in front of every origin. Free TLS, edge cache, cf-connecting-ip and cf-ipcountry in the request headers. The threat-mitigation model is the same on the SaaS and the brand site.

This strip is the reason the two-stack posture is operationally sustainable. Without it, I would be running two completely different operational worlds, each with its own auth library, its own ORM, its own log-shipping, its own deploy pipeline. With it, the only context switch when I move from a production app to this site is the runtime and the framework, both of which are scoped to a single repo at a time.

Why Bun and Hono in production, and not Next.js

Next.js is the wrong shape for the work my production SaaS apps do. Three reasons, in order of weight.

The work is API-shaped, not page-shaped. The paying-customer surfaces are mostly JSON endpoints, dashboards rendered behind auth, background jobs, webhook receivers. The SEO surface on those apps is a marketing landing page and a couple of public docs pages. Hono renders those few public pages with JSX SSR cleanly; the rest is route handlers. Next.js carries machinery that goes unused in this shape.

Schema.org control matters. The marketing surface on a real SaaS needs Product, SoftwareApplication, FAQPage, Organization, and Breadcrumbs structured data, each shaped to my exact org details. Hono lets me write that JSON-LD as a server component literal and ship it inside the document. Next.js does this too, with more abstraction layers between me and the bytes.

Bun starts faster, uses less RAM, and runs the standard Node-style middleware shape Hono targets. On a small Hetzner VPS holding several production apps under one Cloudflare account, that headroom shows up as fewer surprises during traffic spikes.

The hono-honeypot middleware on npm is the artifact of this stack being used in production. Version 1.3.3 at the time of writing, 200-plus attack-pattern regexes derived from months of watching docker compose logs under real malicious traffic. Zero dependencies, 410 Gone default response, runs on every Hono runtime. The full story is in From Docker Logs to hono-honeypot.

Why Next.js and SQLite for the personal-brand site, and every MVP

The job class here is the inverse. The work is page-shaped, not API-shaped. Every public route is a server-rendered page with metadata, JSON-LD, OG image, canonical URL, and a markdown alternate at /blog/<slug>.md. The admin surface is one operator editing one site; the write pattern is bursty and rare, the read pattern is constant.

Next.js 16 absorbs the SEO plumbing for free. App Router gives me file-system routing, native Metadata exports, dynamic sitemap.ts and robots.ts, and the proxy.ts file at the project root that runs on Node.js runtime and replaces the old Edge middleware. All of this without a line of glue code.

SQLite is the database because there is exactly one writer (me) and the rest of the world is reads. better-sqlite3 in WAL mode with a 64MB page cache, 256MB memory-mapped I/O, and 5-second busy timeout. The DB file is bind-mounted into the container; a backup is cp data/music.db data/music.db.bak. No network hop on a query, no managed-DB bill. The migration trigger here is a second app server, or a real user-generated write path. Neither is a 2026 concern.

The rest of the rationale lives in the deep-dive post on this exact decision. Short version: SQLite is the right plan for a content site or single-tenant MVP, and the moment you have a real second writer, Postgres takes over.

Where Postgres takes over from SQLite in the MVP stack

The MVP stack is not always SQLite. The same framework (Next.js 16) and the same runtime (Node.js 24) hold; only the database swaps. The trigger is one of the following:

  • A second writer enters the picture. User accounts, comments, likes, multi-tenant data, anything that generates concurrent writes from outside the admin panel.
  • The MVP becomes the production SaaS. At that point I usually rebuild on the production stack (Bun + Hono) rather than scaling Next.js + Postgres, because the work has shifted from page-shaped to API-shaped and the framework should match. But for a brief window during the transition, Next.js + Postgres is the comfortable middle.
  • A multi-instance deploy. The moment I want two app servers behind a load balancer, SQLite-on-a-bind-mount stops working honestly.

Drizzle on both sides makes the swap close to mechanical. The schema file changes column types in a few places (text autoincrement to serial, integer-timestamp to timestamptz), the connection setup changes one import, and the migrations move from drizzle-orm/better-sqlite3 to drizzle-orm/node-postgres. Application code stays.

The OSS extraction practice: what gets pulled out of production

A second-order effect of the two-stack posture is that the production side becomes a source of open-source extractions, and the personal-brand side becomes the place to write about them.

Two packages I have published this way:

  • hono-honeypot (npm 1.3.3, MIT) is security middleware for Hono.js. It blocks 200-plus reconnaissance patterns from vulnerability scanners (nuclei, nikto, sqlmap, dirbuster, gobuster, wpscan) and bot crawlers before they reach my routes, optionally banning repeat offenders by IP. Pattern set distilled from hundreds of thousands of malicious requests per day across the production apps.
  • dripfeed (npm 0.1.2) is a soak-test CLI for APIs. One request every few seconds for hours, every response logged to a local SQLite database, CI fails on threshold breach. Catches the slow-degradation class of bugs that k6 and Artillery miss because they finish in five minutes.

Both packages exist because the production stack is real, instrumented, and watched. Neither would have shipped from a content site. The OSS-extraction surface is the answer to "how does a solo operator build credibility without releasing demoware": release the small tools that fall out of keeping production alive.

The personal-brand site on the MVP stack is where I write the long-form post explaining each tool. The site itself is also an MCP server, exposing nine admin tools to any MCP-aware client through the admin-MCP layer. That MCP layer sits on the MVP stack because it is content-side, not paying-customer-side. The split holds even there.

What this means for one operator reading framework-comparison posts

Agency stack-comparison posts in 2026 mostly answer "which framework should I pick for my next project". The two-stack posture argues the question itself is the bug. No single framework fits both classes of work a solo founder ships in any given quarter.

The right question is "what job class is this project", and the right answer is one of two stacks I already have running. A new SaaS goes on Bun + Hono + Postgres. A new content site, marketing site, or single-operator MVP goes on Next.js 16 + SQLite. The decision compresses from "research and pick" to "pattern-match and clone".

The failure mode this split prevents, observed in solo-founder communities for years, is the one-framework-for-everything operator who runs Next.js for a write-heavy multi-tenant SaaS, hits scaling pain that has nothing to do with framework quality and everything to do with fit, and concludes Next.js was the wrong call. It was the wrong fit. Pick a stack to the job class, not to your framework preference. Keep two stacks alive, not five. Share the constants strip across both. That is the posture.

FAQ

What does production SaaS stack 2026 mean in practice for a solo founder?

It means a stack picked to survive one operator, multiple production apps, thousands of paying customers, and no per-seat SaaS tax on the platform layer. For me in 2026, that is Bun as the runtime, Hono.js with JSX SSR as the framework, Postgres on Drizzle, BetterAuth for auth, Redis for rate limiting, Docker on a small Hetzner VPS for the deploy, and Cloudflare in front. Several production apps run under this shape without the operational world getting bigger.

Why not just use Next.js for everything?

Next.js is excellent for page-shaped, SEO-driven work. It is heavier than necessary for API-shaped, dashboard-driven SaaS work where the public surface is small and the customer surface is mostly JSON behind auth. The two-stack posture is not a Next.js critique; it is a fit argument. The reverse holds: Hono on Bun would be a poor fit for this personal-brand site, because everything Next.js gives me for free (metadata, sitemap, dynamic OG, markdown alternates) I would have to hand-roll.

Is Hono ready for production in 2026?

Yes. Hono is stable, well-documented, runs on every major JavaScript runtime, and has been my production framework on several SaaS apps. The JSX SSR support is mature enough to ship handcrafted schema.org markup without third-party plugins. The hono-honeypot middleware I publish is built on Hono and runs in production every day across hundreds of thousands of requests per day.

Why Postgres in production and not SQLite?

SQLite is single-writer at the file level. On this site the only writer is me through the admin panel, so SQLite is the correct pick. On a multi-tenant SaaS with concurrent customer writes, billing webhooks, background jobs, and multiple app servers behind a load balancer, the single-writer ceiling is a hard wall. Postgres handles that shape natively. The two-database split is the production stack acknowledging the wall before it bites.

What is the cost of running both stacks on Hetzner?

Single-digit dollars per month in steady state, well below what any managed PaaS would charge for the same load. The margin stays fat from MVP day-one through years of production. The Hetzner-plus-Cloudflare floor is low enough that cost is never the reason I delay shipping or kill a side bet.

What changes when the MVP becomes a real SaaS?

I rebuild on the production stack. The work has shifted from page-shaped to API-shaped, the customer surface has grown, the write pattern has multiplied. The constants strip absorbs most of the migration: the Drizzle schema moves from SQLite types to Postgres types, and route handlers move from Next.js App Router to Hono. Auth, rate limiter, deploy story, and edge layer stay identical.

Does this posture work for a team larger than one?

It works for a small team chosen for compounding skill rather than headcount, the shape I run on most ventures. Two stacks are easier to onboard than five, and the constants strip means a new engineer only learns one auth library, one ORM, one rate limiter, one deploy pipeline. A larger team with specialist roles may need a third lane (heavy-data or analytics) and the constants strip needs more discipline to hold. The shape is correct for the solo-and-small-team range.

Two stacks, one operator, both running on purpose

I do not run two stacks because I cannot pick one. I run two stacks because the work splits cleanly into two job classes and the right tool for each class is not the same tool. The two-stack posture is the operating discipline that comes out of admitting that. Production SaaS gets Bun, Hono, and Postgres. MVPs and the personal-brand site get Next.js 16 and SQLite. Everything in between (auth, ORM, rate limit, container, edge) is identical on both sides, which is what makes carrying two stacks sustainable in the first place. If a project does not fit either lane, the right move is to ask which lane it actually wants to grow into, then start it on that lane from day one.