<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tejas Giri</title>
    <description>The latest articles on DEV Community by Tejas Giri (@tejas_giri_19aa846141b778).</description>
    <link>https://dev.to/tejas_giri_19aa846141b778</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3885464%2Fe1ac176a-4154-41dc-9dc2-62788b877562.png</url>
      <title>DEV Community: Tejas Giri</title>
      <link>https://dev.to/tejas_giri_19aa846141b778</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tejas_giri_19aa846141b778"/>
    <language>en</language>
    <item>
      <title>Stripe rejected my account as an Indian indie dev. Here's what I did instead.</title>
      <dc:creator>Tejas Giri</dc:creator>
      <pubDate>Thu, 07 May 2026 05:10:31 +0000</pubDate>
      <link>https://dev.to/tejas_giri_19aa846141b778/stripe-rejected-my-account-as-an-indian-indie-dev-heres-what-i-did-instead-239k</link>
      <guid>https://dev.to/tejas_giri_19aa846141b778/stripe-rejected-my-account-as-an-indian-indie-dev-heres-what-i-did-instead-239k</guid>
      <description>&lt;p&gt;I'd been building a quiz SaaS for about two months. Auth was working, the core product was tested, and I was finally ready to take payments. I created a Stripe account, filled in everything honestly, and submitted.&lt;/p&gt;

&lt;p&gt;Two days later I got the email.&lt;/p&gt;

&lt;p&gt;Account under review. Please provide business registration documents, GST number, and proof of address matching the registered business name.&lt;/p&gt;

&lt;p&gt;I'm a solo developer. I don't have a registered company. I don't have a GST number because I haven't earned a single rupee from this product yet. The whole point was to validate the idea first and incorporate later if it worked.&lt;/p&gt;

&lt;p&gt;I replied. Explained the situation. Asked what an individual creator without a company should do.&lt;/p&gt;

&lt;p&gt;Four days of silence. Then a generic reply telling me to provide the documents or the account would stay restricted.&lt;/p&gt;

&lt;p&gt;That was the end of my Stripe journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this happens to a lot of us
&lt;/h2&gt;

&lt;p&gt;If you're building from India, Southeast Asia, parts of Latin America, or anywhere Stripe treats as higher risk, this is depressingly common. Stripe is excellent if you're a registered US business. It's a wall if you're a solo person in a country they're cautious about.&lt;/p&gt;

&lt;p&gt;The frustrating part isn't even the rejection. It's the timing. You spend weeks building the product. You're finally ready to charge for it. Momentum is everything at that stage. Four days of waiting on Stripe support kills it. By day five I didn't even feel like opening the project.&lt;/p&gt;

&lt;p&gt;I started looking at alternatives the same evening.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually tried
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Razorpay&lt;/strong&gt; works in India but only for Indian customers. If you want to charge a teacher in the US or Europe, you're stuck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paddle&lt;/strong&gt; looked promising. Merchant of Record, handles tax globally. But the application process was almost as heavy as Stripe and the minimum revenue thresholds made it feel like overkill for someone who hadn't made the first sale yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LemonSqueezy&lt;/strong&gt; was solid. I almost went with it. Then I found Polar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polar
&lt;/h2&gt;

&lt;p&gt;Polar is built specifically for indie developers and creators. The differences that mattered to me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Personal accounts work. No business registration required to start.&lt;/li&gt;
&lt;li&gt;They're a Merchant of Record, which means they collect VAT and sales tax on your behalf and remit it. You don't deal with global tax compliance at all. For a solo developer this is huge — I cannot tell you how much mental load this removes.&lt;/li&gt;
&lt;li&gt;Lower processing fees than Stripe.&lt;/li&gt;
&lt;li&gt;A customer portal is built in. Users can manage their own subscriptions, update payment methods, cancel, resubscribe. Zero extra code from me.&lt;/li&gt;
&lt;li&gt;The sandbox is genuinely usable. I built and tested the entire flow without ever putting in real card details or worrying about test mode quirks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sign up took ten minutes. I had a working sandbox checkout an hour later.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the integration actually looked like
&lt;/h2&gt;

&lt;p&gt;The webhook handling is where most payment integrations get messy. With Polar I had four events to care about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;subscription.created&lt;/code&gt; and &lt;code&gt;subscription.updated&lt;/code&gt; — set the user's plan to pro, store the period end date&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;subscription.canceled&lt;/code&gt; — mark cancel-at-period-end as true (user keeps access until paid period ends)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;subscription.revoked&lt;/code&gt; — flip plan back to free, clear the expiry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the whole subscription state machine. Three flags on the user row: &lt;code&gt;plan&lt;/code&gt;, &lt;code&gt;planExpiresAt&lt;/code&gt;, &lt;code&gt;planCancelAtPeriodEnd&lt;/code&gt;. Webhook updates them. Server reads them when gating features. Done.&lt;/p&gt;

&lt;p&gt;The auth side was easier than I expected because I was using BetterAuth, which has a first-party Polar plugin. Sign-up auto-creates the Polar customer. Checkout, customer portal, and webhook signature verification are all wired in. I wrote roughly 200 lines of billing-specific code total.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest tradeoffs
&lt;/h2&gt;

&lt;p&gt;Polar isn't perfect. The dashboard is younger than Stripe's. The payment method coverage is narrower in some regions. If you're a US business with a finance team that wants every Stripe report under the sun, Polar will feel light.&lt;/p&gt;

&lt;p&gt;But if you're a solo dev trying to ship and charge a few customers and not get blocked by paperwork you don't have, Polar is genuinely the right call. I wish I had found it before the Stripe detour.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built after
&lt;/h2&gt;

&lt;p&gt;I rebuilt that whole auth and payments layer cleanly because by the third project I was tired of redoing it. Next.js 15, BetterAuth, Polar, Drizzle on Neon, Resend for email, Shadcn for the UI. Everything wired together so a new project starts from a working subscription flow on day one instead of week three.&lt;/p&gt;

&lt;p&gt;I packaged it as a boilerplate. If you want to skip the part I just described and start from a setup that already works for non-US developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Live demo: &lt;a href="https://nextjs-better-auth-polar-neon-boil.vercel.app" rel="noopener noreferrer"&gt;https://nextjs-better-auth-polar-neon-boil.vercel.app&lt;/a&gt; (login &lt;code&gt;admin@yopmail.com&lt;/code&gt; / &lt;code&gt;Password123!&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Get it: &lt;a href="https://9928452025183.gumroad.com/l/nextjs-saas-boilerplate" rel="noopener noreferrer"&gt;https://9928452025183.gumroad.com/l/nextjs-saas-boilerplate&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Either way — if you're hitting the same Stripe wall, try Polar before you waste another week on support emails.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>indiehackers</category>
      <category>programming</category>
    </item>
    <item>
      <title>I let Claude Code write an entire feature for a week. Here's what actually broke.</title>
      <dc:creator>Tejas Giri</dc:creator>
      <pubDate>Sun, 03 May 2026 05:34:57 +0000</pubDate>
      <link>https://dev.to/tejas_giri_19aa846141b778/i-let-claude-code-write-an-entire-feature-for-a-week-heres-what-actually-broke-gbp</link>
      <guid>https://dev.to/tejas_giri_19aa846141b778/i-let-claude-code-write-an-entire-feature-for-a-week-heres-what-actually-broke-gbp</guid>
      <description>&lt;p&gt;I've been building things with AI for about a year now. Autocomplete, chat, the usual. But last month I decided to try something different.&lt;/p&gt;

&lt;p&gt;I picked one feature on a side project I'm working on and handed the entire thing to Claude Code. Not "help me write this function." Not "review this PR." The whole feature. Architecture, schema, API, UI, tests. For one full week, I didn't write a single line by hand. I only reviewed, ran, and prompted.&lt;/p&gt;

&lt;p&gt;I wanted to know how far this actually goes when you take the training wheels off. I'm not here to sell you on AI or scare you about it. I'm telling you what I saw.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;The feature was a notification system. User actions trigger events, events get processed, some go to email, some go to in-app. Standard stuff. I'd built something similar before so I knew what good looked like.&lt;/p&gt;

&lt;p&gt;Stack was Next.js, Postgres, a queue. I gave Claude Code access to the repo and described what I wanted. From there I tried to act like a tech lead reviewing a junior dev's work, not a developer writing code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Days 1 and 2 felt like cheating
&lt;/h2&gt;

&lt;p&gt;The first two days were genuinely shocking.&lt;/p&gt;

&lt;p&gt;I described the feature in maybe 200 words. Within an hour I had a working schema, migration files, the events table, a worker that processed jobs, and a basic API. It even wrote tests. Most of it ran on the first try.&lt;/p&gt;

&lt;p&gt;I kept thinking about how long this would have taken me solo. Probably two days of just typing. Schema decisions, naming columns, writing the boilerplate worker code. Done in a morning.&lt;/p&gt;

&lt;p&gt;This is the part everyone shares on Twitter. The "look how fast" part. It's real. I'm not going to pretend it isn't.&lt;/p&gt;

&lt;p&gt;But that's also where most articles stop. So let me keep going.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 3 — the silent bug
&lt;/h2&gt;

&lt;p&gt;By day 3 I had the full feature working end to end. Events firing, getting queued, processed, emails going out. I tested it manually. Looked good. Pushed it to staging. Looked good there too.&lt;/p&gt;

&lt;p&gt;Then I noticed something off. Some notifications were taking 4 seconds to send. Others were instant. Same code path. Same payload size. Same queue.&lt;/p&gt;

&lt;p&gt;I asked Claude Code to investigate. It looked at the code, made some plausible suggestions about the queue config, the database connection pool, retry logic. Nothing fixed it.&lt;/p&gt;

&lt;p&gt;I spent the next 4 hours debugging this myself. Reading code I hadn't written. Adding logs. Watching traces. The bug was small and brutal.&lt;/p&gt;

&lt;p&gt;In one of the worker files, Claude had written something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;processEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;markAsProcessed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spot it? &lt;code&gt;sendNotification&lt;/code&gt; was missing the &lt;code&gt;await&lt;/code&gt;. So sometimes the function finished before the notification actually went out, the worker moved on, and the notification got delayed because Node was busy with the next job.&lt;/p&gt;

&lt;p&gt;Locally this never showed up because nothing else was happening on the event loop. In staging with real traffic, it caused random 4-second delays.&lt;/p&gt;

&lt;p&gt;That single missing &lt;code&gt;await&lt;/code&gt; cost me half a day. And here's the thing that bothered me if I had written that code myself, I would have seen it instantly. Because I'd have been thinking about whether the call was async while writing it. I wasn't thinking. I was reviewing. Reviewing is a different mental mode than writing, and you miss things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 4 — the rewrite loop
&lt;/h2&gt;

&lt;p&gt;This is where the cracks really showed.&lt;/p&gt;

&lt;p&gt;I asked Claude Code to add a feature on top of the existing system. Notification preferences per user. Standard stuff. It started writing.&lt;/p&gt;

&lt;p&gt;Halfway through, I noticed it had subtly rewritten parts of the worker I'd already approved on day 2. Not the same code with new features added. Different code that did roughly the same thing. New variable names. Slightly different error handling. A different retry strategy.&lt;/p&gt;

&lt;p&gt;I asked why it changed those. The answer was something polite about "improved consistency." But the old code was fine. I'd already tested it. Now I had to re-test the parts that worked yesterday because they weren't the same code anymore.&lt;/p&gt;

&lt;p&gt;This kept happening for the rest of the day. Every new request seemed to drag in unrelated changes. I started noticing how much of my time was going into "why did you change that, change it back" instead of actually moving forward.&lt;/p&gt;

&lt;p&gt;A senior dev I trust once told me the hardest skill in code review isn't finding bugs. It's noticing what changed that shouldn't have. With AI doing the writing, that skill becomes the entire job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 5 — confidence with no basis
&lt;/h2&gt;

&lt;p&gt;The most unsettling moment came on Friday.&lt;/p&gt;

&lt;p&gt;I asked Claude Code to add rate limiting to the notification API. It wrote the code. Confident, clean, well-named functions. Used a Redis-based sliding window. Beautiful.&lt;/p&gt;

&lt;p&gt;Except we weren't using Redis in this project. We never had been. I'd never mentioned Redis. There was no Redis client installed. It just decided we used Redis because that's what most rate limiters in its training data use.&lt;/p&gt;

&lt;p&gt;When I pointed this out it apologized and rewrote it with a simpler in-memory approach. Fine. But I sat there for a minute thinking what if I hadn't caught that? What if I'd just run npm install redis and added a Redis instance to my infrastructure because the AI suggested it? On a different team, a less careful reviewer would absolutely have shipped that.&lt;/p&gt;

&lt;p&gt;The code itself was good. The assumption underneath it was completely fabricated. And the confidence was the same either way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it's actually good for
&lt;/h2&gt;

&lt;p&gt;I want to be fair here because I don't want to write another doom post. By the end of the week I had a real working feature shipped. That's not nothing.&lt;/p&gt;

&lt;p&gt;What it was actually great at:&lt;/p&gt;

&lt;p&gt;The early scaffolding when there's no context to lose. Schema design, initial file structure, the boilerplate parts. The first 60 percent was genuinely faster.&lt;/p&gt;

&lt;p&gt;Tedious but mechanical work. Writing test cases for code I'd already approved. Generating types from a schema. Converting one shape of data to another. Migration files. README updates. All the things that drain a developer's day without engaging their brain.&lt;/p&gt;

&lt;p&gt;Exploration and unfamiliar territory. When I needed to integrate with a service I'd never used, having something that could read the docs and write a first attempt was useful. I'd learn faster from fixing its mistakes than from staring at empty documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it was bad at
&lt;/h2&gt;

&lt;p&gt;Anything where context mattered. The longer the feature got, the more it forgot what we'd already decided. By day 4 I was repeating myself constantly. "We're not using Redis." "Don't change the worker file." "The retry logic is correct, leave it."&lt;/p&gt;

&lt;p&gt;Subtle async correctness. The missing &lt;code&gt;await&lt;/code&gt; was just the start. I found three more like it that week. Promise chains where the outer code didn't wait properly. Database transactions that weren't transactions because one query escaped the wrapper. Stuff that runs fine in tests and breaks under real load.&lt;/p&gt;

&lt;p&gt;Knowing when to stop. A human dev knows when a feature is done. AI keeps suggesting improvements. New features. Refactors. Better names. After a while you spend more time saying "no, this is fine" than actually building.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed in how I work
&lt;/h2&gt;

&lt;p&gt;I'm still using Claude Code. Heavily. But I've changed how.&lt;/p&gt;

&lt;p&gt;I don't hand it whole features anymore. I hand it pieces. Small enough that I can hold the whole change in my head when I review. Big enough that I'm not just doing autocomplete.&lt;/p&gt;

&lt;p&gt;I read every line that gets committed. Not skim. Read. The cost of a missed &lt;code&gt;await&lt;/code&gt; is higher than the time saved by not reading.&lt;/p&gt;

&lt;p&gt;I keep my own context. The architectural decisions, the naming conventions, what we use and don't use I write these in a single document and reference it in every prompt. Otherwise I'm fighting the same battles every session.&lt;/p&gt;

&lt;p&gt;And I never let it write code in areas where the cost of being wrong is high. Auth flows. Payment webhooks. Anything that touches money or sessions. There I write it myself, slowly, paranoid, rereading. AI helps me explore and scaffold. I do the parts where being wrong matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real takeaway
&lt;/h2&gt;

&lt;p&gt;The week wasn't a failure. It also wasn't the productivity miracle the demos sell.&lt;/p&gt;

&lt;p&gt;What I actually learned was about myself, not the tool. I noticed how my brain felt different when I was reviewing instead of writing. Less engaged. Less suspicious. More likely to nod and approve.&lt;/p&gt;

&lt;p&gt;Writing code is partly how you understand the system. When you stop writing, you stop understanding, and you start trusting. And trust is exactly the wrong mode for shipping software.&lt;/p&gt;

&lt;p&gt;The developers who'll do well over the next few years aren't the ones who use AI the most. They're the ones who keep the parts of their brain that catch a missing &lt;code&gt;await&lt;/code&gt; even when they're tired, even when the code looks fine, even when the AI sounds confident.&lt;/p&gt;

&lt;p&gt;The tool is good. Use it. Just don't let it use you.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>claude</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Stop using Prisma on Vercel. Seriously</title>
      <dc:creator>Tejas Giri</dc:creator>
      <pubDate>Sat, 25 Apr 2026 03:29:54 +0000</pubDate>
      <link>https://dev.to/tejas_giri_19aa846141b778/stop-using-prisma-on-vercel-seriously-3lmh</link>
      <guid>https://dev.to/tejas_giri_19aa846141b778/stop-using-prisma-on-vercel-seriously-3lmh</guid>
      <description>&lt;p&gt;I'm going to make some Prisma fans angry. That's fine.&lt;/p&gt;

&lt;p&gt;I shipped my last three SaaS projects on Next.js + Vercel + Postgres. The first two used Prisma because that's what every tutorial recommends. The third one I switched to Drizzle.&lt;/p&gt;

&lt;p&gt;Cold start on a fresh deploy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prisma: 2.8 seconds&lt;/li&gt;
&lt;li&gt;Drizzle: 180 milliseconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's not a typo. That's the difference between a user thinking your app is broken and your app feeling instant. And it's not a benchmark I cherry-picked from a blog post that's the p95 from my own Vercel logs across two weeks of production traffic.&lt;/p&gt;

&lt;p&gt;If you're building on Vercel (or any serverless platform Netlify, Cloudflare Workers, AWS Lambda) and you're still reaching for Prisma because that's what the tutorial said, this article is for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "cold start" actually means and why it matters more than you think
&lt;/h2&gt;

&lt;p&gt;Every serverless function on Vercel starts cold the first time it's hit. Cold means the container doesn't exist yet Vercel has to spin up a fresh Node.js process, load your code, initialize your dependencies, and then run your handler.&lt;/p&gt;

&lt;p&gt;Once the container is warm, subsequent requests are fast. But "warm" expires. On Vercel's hobby tier, containers go cold after about 15 seconds of inactivity. On Pro it's longer but still measured in minutes, not hours.&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first user to hit any given route after a quiet period waits for cold start&lt;/li&gt;
&lt;li&gt;If your app has 10 routes, you have 10 separate cold-start surfaces&lt;/li&gt;
&lt;li&gt;The bigger your dependency graph, the slower every cold start gets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prisma is one of the biggest dependencies you can add to a Node.js project. The reason has nothing to do with code quality and everything to do with how Prisma is built.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real problem: Prisma's architecture wasn't built for serverless
&lt;/h2&gt;

&lt;p&gt;Prisma is two things bolted together. There's a TypeScript layer that generates types and gives you the nice query API. And underneath that, there's a query engine written in Rust, compiled to a native binary that ships in your &lt;code&gt;node_modules&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When your serverless function cold-starts, Node.js has to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load &lt;code&gt;@prisma/client&lt;/code&gt; (a few hundred KB of generated TypeScript)&lt;/li&gt;
&lt;li&gt;Locate the correct query engine binary for the runtime architecture&lt;/li&gt;
&lt;li&gt;Spawn a child process for the query engine&lt;/li&gt;
&lt;li&gt;Establish IPC between Node and the engine&lt;/li&gt;
&lt;li&gt;Initialize the connection pool&lt;/li&gt;
&lt;li&gt;Then, finally, run your query&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On a beefy dev machine you don't notice. On a Vercel cold start, every one of those steps adds milliseconds, and they compound.&lt;/p&gt;

&lt;p&gt;The official Prisma docs acknowledge this. They have a whole page on cold starts. Their suggested fix is to use Prisma Accelerate a paid connection pooling service that, conveniently, Prisma sells. The pricing starts free but ramps fast, and now you have another service in your critical path that can fail.&lt;/p&gt;

&lt;p&gt;I tried Accelerate. It works. It also adds another network hop, costs money, and doesn't solve the underlying problem it just hides it behind a cache.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Drizzle does differently
&lt;/h2&gt;

&lt;p&gt;Drizzle is a query builder, not an ORM in the Prisma sense. There's no query engine. There's no binary. There's no code generation step that you run separately.&lt;/p&gt;

&lt;p&gt;When you write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usersTable&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usersTable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That compiles to plain SQL at build time. The runtime is just a thin wrapper that sends SQL strings to whatever database driver you're using. For Neon (which is what I use now), the driver is &lt;code&gt;@neondatabase/serverless&lt;/code&gt; it speaks Postgres over HTTP, no TCP connection pooling needed, designed for serverless from day one.&lt;/p&gt;

&lt;p&gt;The whole runtime fits in your function bundle. There's no separate process. There's no IPC. There's no waiting for a Rust binary to wake up. Cold start is essentially "load some TypeScript, send an HTTP request."&lt;/p&gt;

&lt;p&gt;That's where the 180ms vs 2.8s gap comes from. It's not magic, it's not better code it's that one architecture was designed for long-running servers and the other was designed for serverless.&lt;/p&gt;

&lt;h2&gt;
  
  
  "But the DX is worse, right?"
&lt;/h2&gt;

&lt;p&gt;This is what every Prisma defender says. It's worth being honest about.&lt;/p&gt;

&lt;p&gt;For 90% of queries, Drizzle's API is just as readable as Prisma's. Find by ID, insert, update, delete with a where clause these all look basically the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Prisma&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Drizzle&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findFirst&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where Drizzle wins: you can drop into raw SQL anywhere, mix and match, and the migrations are plain &lt;code&gt;.sql&lt;/code&gt; files you can read and edit. When something breaks in production at 2am, you can &lt;code&gt;psql&lt;/code&gt; into the database and run the same query.&lt;/p&gt;

&lt;p&gt;Where Prisma wins: relations and nested includes are slightly nicer in Prisma. The auto-completion for related fields is a touch better. If you're doing complex graph queries through 4 levels of relations, Prisma still has the edge in ergonomics.&lt;/p&gt;

&lt;p&gt;For a typical SaaS app users, sessions, subscriptions, a few business entities you will not feel this difference. You will feel the cold start difference every single day.&lt;/p&gt;

&lt;h2&gt;
  
  
  "But I'm not on serverless"
&lt;/h2&gt;

&lt;p&gt;Fair. If you're deploying to a long-running container Railway, Fly, Render, your own VPS Prisma's cold start cost is paid once at process start and then forgotten. The trade-off math is different. Prisma is genuinely fine there.&lt;/p&gt;

&lt;p&gt;But if you're on Vercel, Netlify, Cloudflare, or any serverless platform where cold starts happen regularly, you're paying that 2-3 second tax every time the platform decides to recycle a container. Which, for a low-traffic SaaS in its early days, is constantly.&lt;/p&gt;

&lt;p&gt;The cruel irony: the smaller your app, the more it gets recycled, the more cold starts your few users hit, the worse Prisma feels. By the time you have enough traffic to keep containers warm, you've already lost the early users who bounced because the first page took 3 seconds to render.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually use now
&lt;/h2&gt;

&lt;p&gt;For the last year, every Next.js project I've shipped uses the same data layer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Drizzle ORM&lt;/strong&gt; for queries and migrations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neon&lt;/strong&gt; for serverless Postgres (scales to zero, free tier is generous, branching for staging is great)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@neondatabase/serverless&lt;/code&gt;&lt;/strong&gt; as the driver speaks Postgres over HTTP, perfect for Vercel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole thing is maybe 50 lines of setup. Migrations are SQL files I can read. Cold starts are imperceptible. When something breaks, I can debug it because there's no Rust binary in the middle.&lt;/p&gt;

&lt;h2&gt;
  
  
  The boring conclusion
&lt;/h2&gt;

&lt;p&gt;Prisma isn't bad. The Prisma team is talented and the project is well-maintained. The problem is that Prisma was designed in 2018-2019 when "Node.js backend" meant "long-running Express server on AWS EC2." Serverless was a niche. The architecture reflects that era.&lt;/p&gt;

&lt;p&gt;The default stack for Next.js in 2026 is serverless. Vercel is serverless. Cloudflare Workers is serverless. Even traditional hosts are pushing edge runtimes. Recommending Prisma to a beginner who's deploying to Vercel is recommending a tool that was built for a different deployment model and hoping they won't notice the cost.&lt;/p&gt;

&lt;p&gt;They notice. They notice when their landing page takes 3 seconds to load on the first visit of the day. They notice when their Lighthouse score is in the 60s. They notice when paying users open a ticket asking why the dashboard "freezes for a few seconds."&lt;/p&gt;

&lt;p&gt;If you're starting a new Next.js project on Vercel today, try Drizzle. Spend an afternoon with it. If you hate it, go back to Prisma you've lost half a day. If you like it, you've saved your users 2.5 seconds on every cold start, forever.&lt;/p&gt;

&lt;p&gt;That's the whole pitch. The numbers don't lie.&lt;/p&gt;




&lt;p&gt;I write a Next.js + BetterAuth + Polar + Drizzle boilerplate that uses exactly this stack auth, payments, admin panel, blog, all wired together with cold starts under 200ms. Live demo (&lt;a href="mailto:admin@yopmail.com"&gt;admin@yopmail.com&lt;/a&gt; / Password123!): &lt;a href="https://nextjs-better-auth-polar-neon-boil.vercel.app" rel="noopener noreferrer"&gt;https://nextjs-better-auth-polar-neon-boil.vercel.app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>prisma</category>
      <category>drizzle</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why I replaced Stripe with Polar, Prisma with Drizzle, and Clerk with BetterAuth and never looked back</title>
      <dc:creator>Tejas Giri</dc:creator>
      <pubDate>Sun, 19 Apr 2026 10:30:10 +0000</pubDate>
      <link>https://dev.to/tejas_giri_19aa846141b778/why-i-replaced-stripe-with-polar-prisma-with-drizzle-and-clerk-with-betterauth-and-never-looked-f63</link>
      <guid>https://dev.to/tejas_giri_19aa846141b778/why-i-replaced-stripe-with-polar-prisma-with-drizzle-and-clerk-with-betterauth-and-never-looked-f63</guid>
      <description>&lt;p&gt;I want to be upfront about something before you read this.&lt;/p&gt;

&lt;p&gt;I'm not a tech influencer. I'm not being paid by any of these companies. I'm just a developer who spent the last two years building SaaS products and hitting the same walls over and over until I finally stopped and asked myself why am I still using these tools?&lt;/p&gt;

&lt;p&gt;This is that story.&lt;/p&gt;

&lt;h2&gt;
  
  
  The moment I knew something had to change
&lt;/h2&gt;

&lt;p&gt;I was three days into setting up payments for my latest project. Not building the product. Not writing features. Just trying to get Stripe to accept my account.&lt;/p&gt;

&lt;p&gt;I'm an indie developer. Solo. No registered business. Just me and my laptop trying to build something people would pay for.&lt;/p&gt;

&lt;p&gt;Stripe kept asking for business registration documents. My personal account got flagged for "additional review." Support took four days to respond with a template email that didn't answer my question.&lt;/p&gt;

&lt;p&gt;Meanwhile the idea in my head was getting stale. The momentum was dying. And I hadn't written a single line of actual product code yet.&lt;/p&gt;

&lt;p&gt;That was the moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stripe → Polar
&lt;/h2&gt;

&lt;p&gt;I want to be fair to Stripe. It's an incredible product. The documentation is some of the best I've ever read. The developer experience for someone with a proper business setup is genuinely excellent.&lt;/p&gt;

&lt;p&gt;But for indie developers especially outside the US and UK it's a nightmare.&lt;/p&gt;

&lt;p&gt;A friend mentioned Polar. I was skeptical. I'd never heard of it and honestly assumed it was some half-baked alternative that would cause more problems than it solved.&lt;/p&gt;

&lt;p&gt;I had it working in three hours.&lt;/p&gt;

&lt;p&gt;Personal account. No business registration. No documents. No four day support wait. Just an API key and a product ID and I was taking real payments.&lt;/p&gt;

&lt;p&gt;But here's what actually surprised me beyond the setup. Polar is Merchant of Record. That means they handle VAT, sales tax, and tax compliance globally. If you've ever tried to figure out EU VAT as a solo developer you know exactly why this matters. With Stripe you're responsible for all of it. With Polar it's just handled.&lt;/p&gt;

&lt;p&gt;The webhook integration is clean. The customer portal is built in no extra code to build a billing management page. The subscription flows just work.&lt;/p&gt;

&lt;p&gt;Lower fees than Stripe. Works globally without a registered business. Built by people who actually understand the indie hacker workflow. I haven't touched Stripe since.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prisma → Drizzle
&lt;/h2&gt;

&lt;p&gt;This one is harder to explain because Prisma is genuinely good. The developer experience is polished. The schema syntax is readable. The migration tooling works.&lt;/p&gt;

&lt;p&gt;The problem for me came when I deployed to Vercel. Cold starts.&lt;/p&gt;

&lt;p&gt;Prisma generates a large binary client. On serverless environments Vercel, Netlify, any edge runtime that binary takes time to initialize. Not seconds. But enough that your first request after inactivity feels sluggish. Enough that users notice.&lt;/p&gt;

&lt;p&gt;I switched to Drizzle and the difference was immediate. No binary client. Tiny bundle. Cold starts essentially disappear. And the TypeScript support isn't just good it's the best type inference I've seen in any ORM.&lt;/p&gt;

&lt;p&gt;The syntax takes a few days to get used to if you're coming from Prisma. But once it clicks, writing database queries feels like writing TypeScript rather than fighting a query builder.&lt;/p&gt;

&lt;p&gt;The other thing I didn't expect migrations are plain SQL files. You can read them. You know exactly what's running against your database. With Prisma I always had this slight anxiety about what the migration was actually doing. With Drizzle it's just SQL. No magic. No surprises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clerk → BetterAuth
&lt;/h2&gt;

&lt;p&gt;Okay. This is the one I feel most strongly about.&lt;/p&gt;

&lt;p&gt;I used Clerk for two projects. The onboarding experience is genuinely beautiful. You're up and running in 20 minutes. The prebuilt components look great. Everything just works. Until you get your first bill.&lt;/p&gt;

&lt;p&gt;Clerk's free tier is generous. But the moment you start growing real users, real traffic the pricing jumps fast. I've talked to developers paying $200-400 a month in Clerk fees before their product was even profitable.&lt;/p&gt;

&lt;p&gt;But the money isn't even the main reason I left. It's the data ownership problem.&lt;/p&gt;

&lt;p&gt;With Clerk your users live in Clerk's infrastructure. Not your database. If Clerk has an outage your auth is down. If Clerk changes their pricing dramatically you're stuck because migration is painful. If you need custom user fields or complex role logic you're working around Clerk's opinions about how auth should work.&lt;/p&gt;

&lt;p&gt;I want my users in my database. Full stop.&lt;/p&gt;

&lt;p&gt;BetterAuth is a library. It runs in your app. Your users are in your Postgres database from day one. No external service. No dependency on someone else's infrastructure. No surprise bills at scale.&lt;/p&gt;

&lt;p&gt;The TypeScript support is first class better than NextAuth v5 which has been in beta for what feels like forever. The plugin system is genuinely well designed. Adding OAuth providers, magic links, two factor auth, admin features it's all plugins that compose cleanly instead of fighting each other.&lt;/p&gt;

&lt;p&gt;And the Polar plugin means your auth and payments are integrated out of the box. User signs up, Polar customer is created automatically. Subscription webhook fires, user plan updates in your database. It's the kind of integration that would take you a day to wire up manually just there.&lt;/p&gt;

&lt;p&gt;I haven't missed Clerk once.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this stack actually looks like
&lt;/h2&gt;

&lt;p&gt;After going through all of this I ended up with a stack I'm genuinely happy with for the first time. Next.js 15 for the framework. BetterAuth for auth. Polar for payments. Drizzle ORM on Neon serverless Postgres for the database. Resend for emails. Shadcn/ui and Tailwind v4 for UI.&lt;/p&gt;

&lt;p&gt;Every piece of this was chosen because I hit a real problem with the alternative. Not because of a YouTube tutorial. Not because of a Twitter thread. Because I used the other thing and it hurt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I didn't expect
&lt;/h2&gt;

&lt;p&gt;When I finally had this stack working together really working, not just a demo but production traffic I realized something. I had rebuilt the same foundation for the fourth time in two years. Auth. Payments. Email. Admin panel. Webhooks. Protected routes. Plan-based feature gates. Every project. Same setup. Different bugs.&lt;/p&gt;

&lt;p&gt;So I packaged it. Cleaned up the code, documented every decision, wrote a setup guide, and turned it into a boilerplate that other developers can use instead of going through the same three weeks of infrastructure work I keep going through.&lt;/p&gt;

&lt;p&gt;If you're starting a new project and you want this stack without the research and debugging it's available. Demo is live so you can see it before deciding. Everything I described in this article is wired together and working.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextjs-better-auth-polar-neon-boil.vercel.app/auth/sign-in" rel="noopener noreferrer"&gt;demo link&lt;/a&gt; — &lt;a href="mailto:admin@yopmail.com"&gt;admin@yopmail.com&lt;/a&gt; / Password123!&lt;br&gt;
&lt;a href="https://9928452025183.gumroad.com/l/nextjs-saas-boilerplate" rel="noopener noreferrer"&gt;gumroad link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  If you take nothing else from this
&lt;/h2&gt;

&lt;p&gt;Try Polar if you're struggling with Stripe account approval or global payment complexity. Try Drizzle if cold starts or bundle size matter to your deployment. Try BetterAuth if you're tired of paying for auth at scale or want your user data in your own database.&lt;/p&gt;

&lt;p&gt;None of these are perfect. But for indie developers building SaaS products solo they're the best combination I've found. And I've tried a lot of combinations.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>stripe</category>
      <category>polar</category>
      <category>clerk</category>
    </item>
  </channel>
</rss>
