<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>SaaS — Lakshmi Narasimhan</title><link>https://lakshminp.com/tags/saas/</link><description>I help developers build, deploy, and distribute their SaaS without hiring a team. Long-running notes on systems, AI internals, Carnatic music, fiction craft, and whatever else collides interestingly.</description><generator>Hugo + lakshminp theme</generator><language>en-us</language><lastBuildDate>Mon, 15 Jun 2026 00:00:00 +0000</lastBuildDate><managingEditor>Lakshmi Narasimhan</managingEditor><webMaster>Lakshmi Narasimhan</webMaster><copyright>© 2026 Lakshmi Narasimhan</copyright><atom:link href="https://lakshminp.com/tags/saas/feed.xml" rel="self" type="application/rss+xml"/><item><title>How to Build a SaaS with Claude Code in a Weekend (Not a Quarter)</title><link>https://lakshminp.com/2026/06/build-saas-with-claude-code/</link><pubDate>Mon, 15 Jun 2026 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2026/06/build-saas-with-claude-code/</guid><category>essays</category><category>claude-code</category><category>ai-coding</category><category>saas</category><description>I caught up with one of my mentees last weekend. Just talking shop. He’s a solid developer, he’s got the itch to build a side project, and he’s brand new to agentic coding. Somewhere in that conversation I realized I was reciting an entire playbook off the top of my head — so I’m writing it down. If you can write code and you’re staring at Claude Code wondering how to actually build and ship a SaaS with it, this is for you.</description><content:encoded><![CDATA[<p>I caught up with one of my mentees last weekend. Just talking shop. He&rsquo;s a solid developer, he&rsquo;s got the itch to build a side project, and he&rsquo;s brand new to agentic coding. Somewhere in that conversation I realized I was reciting an entire playbook off the top of my head — so I&rsquo;m writing it down. If you can write code and you&rsquo;re staring at Claude Code wondering how to actually build and ship a SaaS with it, this is for you.</p>
<p>A quick word on <em>why now</em>, before the <em>how</em>. Two reasons, and you&rsquo;ve heard at least one:</p>
<ol>
<li>AI is eating the jobs. You can&rsquo;t open your phone without someone reminding you. Enough said.</li>
<li>The AI subsidy is going to end. Right now you&rsquo;re building on frontier models that cost the labs more than they charge you. That window closes. <a href="/2026/03/ai-subsidy-window-developers/" class="lnp-link">I wrote about this here</a></li>
</ol>
<p>Maybe both happen. Either way the move is the same: build the muscle now, while it&rsquo;s cheap and you still have an edge.</p>
<h2 id="1-what-to-build">1. What to build</h2>
<p>Scratch your own itch. Do not spend three weeks &ldquo;researching the market&rdquo; to discover what people want. If you have a problem an app would fix, give yourself permission to build it. We&rsquo;ll worry about market size <em>after</em> it ships.</p>
<p>Market research used to be load-bearing because building was expensive and being wrong was catastrophic — months of work, real money, dead on arrival. That math is gone. You can ship an app over a weekend now. The cost of being wrong is one wasted Saturday.</p>
<p>Paul Graham makes the sharper version of this point: build what <em>you</em> want, because — as he writes in <a href="https://paulgraham.com/earn.html" rel="external nofollow noopener" class="lnp-link">How to Earn a Billion Dollars</a> — &ldquo;your own needs are uniquely valuable, because your needs predict future demand.&rdquo; You&rsquo;re not guessing what strangers want. You&rsquo;re scratching an itch you can actually feel.</p>
<p>I&rsquo;ve written about finding an idea and shipping it in a single sitting — <a href="/2026/01/claude-code-ship-one-session/" class="lnp-link">here</a>.</p>
<h2 id="2-know-where-youre-standing">2. Know where you&rsquo;re standing</h2>
<p>Be honest about your starting point: do you have real development experience, or do you need to ramp up first? <a href="/2025/10/ai-coding-prerequisites/" class="lnp-link">Here&rsquo;s what I&rsquo;d master before letting AI build for you</a></p>
<p>Yes, there are people on the internet shipping apps with zero coding background. Maybe. But if you can&rsquo;t read what Claude Code writes, you can&rsquo;t steer it — and you&rsquo;ll feel that the first time it confidently drives into a wall. You don&rsquo;t need a CS degree. You need enough of a mental model to call BS. The good news: you can learn development <em>from</em> Claude Code while you build <em>with</em> it. Learning and building at the same time is completely legitimate — it&rsquo;s how I pick up half the things I use.</p>
<h2 id="3-how-i-actually-build">3. How I actually build</h2>
<p>There&rsquo;s no one true way. This is what works for me; your mileage may vary.</p>
<p>First, the unglamorous part: get the Claude Code Max plan. The $100 tier, or the $200 one if you can swing it. You cannot build anything meaningful on the cheap plans, and you&rsquo;ll discover exactly why about four hours into your first real session. Don&rsquo;t flinch at the price — it&rsquo;s still cheaper than a tutor or a freelancer, and it doesn&rsquo;t take lunch breaks. Plus the quality is consistently good.</p>
<h3 id="why-claude-code-and-not-the-benchmark-topping-model-of-the-week">Why Claude Code and not [the benchmark-topping model of the week]?</h3>
<p>Because building a startup is already exhausting, and you do not have spare energy to spend benchmarking models and sharpening tools instead of shipping. Pick what works and stick with it.</p>
<p>Codex is a close second — genuinely good, and I keep it around. But Claude Code stays a step ahead for actually building apps, and after working with both, I reach for it first. Use both if you like. Just don&rsquo;t turn tool selection into the project.</p>
<h3 id="boring-choices-win">Boring choices win</h3>
<p>Freeze your stack early — backend, frontend, database. 80% of it is identical across every app you&rsquo;ll ever build, so stop re-deciding it every time. And don&rsquo;t obsess over scale and optimization. Those are problems you <em>earn</em> by being successful. Good problems. You don&rsquo;t have them yet.</p>
<h2 id="4-specs-and-context-engineering-the-part-that-decides-everything">4. Specs and context engineering: the part that decides everything</h2>
<p>Two things determine whether you get your money&rsquo;s worth out of Claude Code:</p>
<ol>
<li>The specification</li>
<li>Context engineering</li>
</ol>
<h3 id="the-spec">The spec</h3>
<p>The more specific you are, the better the output. &ldquo;Build a to-do app&rdquo; gets you slop. &ldquo;Here&rsquo;s the auth flow, here&rsquo;s the data model, here are the exact features&rdquo; gets you something you can use. Spend real time here, before a single line of code gets written. <a href="/2025/12/stop-making-claude-code-guess/" class="lnp-link">More on this</a></p>
<p>The move that works best: make Claude Code interview <em>you</em> about the spec. If you can&rsquo;t answer its questions, you can&rsquo;t articulate the feature — and if you can&rsquo;t articulate it, you can&rsquo;t build it. By the time the spec is done, the MVP should have zero grey areas.</p>
<h3 id="context-engineering">Context engineering</h3>
<p>Even the best frontier model starts coding like it&rsquo;s three drinks deep once the context fills up. So you manage it.</p>
<p>This takes me back to my assembly-language days — limited registers, limited memory, every instruction written with one eye on the resources you didn&rsquo;t have. LLM context is that same constraint in new clothes. You get roughly 200k tokens, and that&rsquo;s nowhere near enough to hold your whole app in its head at once.</p>
<p>So: one task per session. Two at the absolute most. Which means breaking the spec into session-sized tasks and tracking what&rsquo;s done, what&rsquo;s in flight, what&rsquo;s blocked, and what depends on what.</p>
<p>A markdown to-do file is a terrible way to do this and a worse use of your time. I use <strong>beads</strong>. Adopted it early, still on it. It&rsquo;s the fix for <a href="/2025/11/ai-agent-memory-persistence/" class="lnp-link">an agent that wakes up every morning with no memory of what you did yesterday</a>.</p>
<p>This practice is also a lot kinder for your token limits.</p>
<p>Two flavors:</p>
<ul>
<li>the original, by the author — <a href="https://github.com/gastownhall/beads" rel="external nofollow noopener" class="lnp-link">gastownhall/beads</a></li>
<li><strong>beads-rust</strong>, a simpler, more stable reimplementation of the spec in Rust — <a href="https://github.com/Dicklesworthstone/beads_rust" rel="external nofollow noopener" class="lnp-link">Dicklesworthstone/beads_rust</a></li>
</ul>
<p>Use either. I landed on beads-rust. Pick your poison.</p>
<p>You also need memory <em>across</em> sessions. You&rsquo;ll remember you fixed a bug two weeks ago; the model in today&rsquo;s session won&rsquo;t, and it&rsquo;ll cheerfully hand you a wrong answer when you ask &ldquo;did we already fix this?&rdquo; I use <strong>claude-mem</strong> for that — <a href="https://github.com/thedotmack/claude-mem" rel="external nofollow noopener" class="lnp-link">thedotmack/claude-mem</a>.</p>
<p>Point a Claude Code session at both repos and it&rsquo;ll install them for you. (Yes, these work with Codex too — but again: shipping or tuning? The clock is running.)</p>
<p>Remember that spec? Hand it to your beads skill and it breaks down into a clean task list. Ask Claude to pull the high-leverage beads and start there — never more than two in flight.</p>
<h3 id="your-claudemd-matters">Your CLAUDE.md matters</h3>
<p>Treat it as a compass, not a second spec. The practices that matter (write the tests first), how the app deploys, the handful of goals you&rsquo;re aiming at. Keep it light — <a href="/2026/04/claude-md-best-practices/" class="lnp-link">cramming a novel into CLAUDE.md is the fastest way to make Claude dumber</a>.</p>
<h3 id="one-more-tool">One more tool</h3>
<p><a href="https://github.com/sirmalloc/ccstatusline" rel="external nofollow noopener" class="lnp-link">ccstatusline</a>. Configure it to show your remaining context percentage. It&rsquo;s the fuel gauge that tells you whether to keep driving or pull over and start a fresh session.</p>
<p>Then it&rsquo;s rinse and repeat: feed beads to Claude, do the manual QA yourself, close the bead, next one. A few sessions in, a sliver of a working MVP starts to emerge. When you&rsquo;re happy with it, you ship.</p>
<h2 id="5-deploying-it-without-the-kubernetes-tax">5. Deploying it (without the Kubernetes tax)</h2>
<p>I was a Kubernetes guy for years. Deployed everything on it. I no longer recommend it for solo developers — <a href="/2025/12/kubernetes-indie-dev-alternative/" class="lnp-link">I explain why here</a>. It still has its place and time; your weekend project is neither.</p>
<p>Use <strong><a href="https://kamal-deploy.org" rel="external nofollow noopener" class="lnp-link">Kamal</a></strong> instead. Think of it as the compromise between Docker Compose and Kubernetes — Compose&rsquo;s simplicity, enough of Kubernetes&rsquo; robustness, none of the YAML despair.</p>
<p>I&rsquo;m also building <a href="https://vmkit.dev/" rel="external nofollow noopener" class="lnp-link">VMKit</a> to make this part disappear entirely — deploy without learning the nitty-gritty unless you want to.</p>
<p>Then there&rsquo;s the wiring you don&rsquo;t think about until it bites: monitoring and ops (I run mine through MCPs — <a href="/2026/01/30-dollar-saas-stack/" class="lnp-link">the $30 stack</a>), payments (Stripe; if you&rsquo;re in India, Dodo Payments), and distribution — marketing and positioning, which is a beast all its own. Each of these deserves its own post.</p>
<h2 id="tldr">TL;DR</h2>
<ul>
<li>Build for your own itch. Shipping is cheaper than market research now.</li>
<li>Get the Claude Code Max plan ($100, ideally $200). Don&rsquo;t tool-shop.</li>
<li>Spend your time on the spec — let Claude interview you until there are no grey areas.</li>
<li>Engineer your context: one task per session, tracked with beads, remembered with claude-mem.</li>
<li>Keep CLAUDE.md light. Watch your context gauge.</li>
<li>Deploy with Kamal, not Kubernetes. Wire payments and monitoring last.</li>
<li>The whole thing is a weekend, not a quarter.</li>
</ul>
]]></content:encoded></item><item><title>Your SaaS Audience Doubled. Half of Them Are AI Agents.</title><link>https://lakshminp.com/2026/03/build-mcp-server-first-saas/</link><pubDate>Mon, 16 Mar 2026 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2026/03/build-mcp-server-first-saas/</guid><category>essays</category><category>saas</category><category>ai-coding</category><description>I was building the wrong product for about three weeks before I noticed.
I’d started x-intel as a SuperX clone — essentially a better analytics dashboard for X. Charts, follower graphs, engagement breakdowns, competitor tracking. The kind of thing where you look at a number, decide you feel bad about it, and close the tab.
And then I was chatting with Claude about the onboarding flow, and I said something like: “when I say onboarding, I mean the app gets my context and goals, then charts a strategy, periodically reviews it, and course corrects.”</description><content:encoded><![CDATA[<p>I was building the wrong product for about three weeks before I noticed.</p>
<p>I’d started x-intel as a SuperX clone — essentially a better analytics dashboard for X. Charts, follower graphs, engagement breakdowns, competitor tracking. The kind of thing where you look at a number, decide you feel bad about it, and close the tab.</p>
<p>And then I was chatting with Claude about the onboarding flow, and I said something like: “when I say onboarding, I mean the app gets my context and goals, then charts a strategy, periodically reviews it, and course corrects.”</p>
<p>Claude’s response stopped me: <em>“That’s a fundamentally different product. Less ‘setup wizard’, more ‘AI strategist that lives in your X account.’</em>“</p>
<p>I stared at that for a while. Then I realized I’d been building the audit view and calling it the product.</p>
<p>The dashboard isn’t the product. The dashboard is what humans look at after the AI already figured out what’s happening.</p>
<p>Build the MCP server first. The dashboard ships itself.</p>
<p>The problem is everyone’s still building it the other way.</p>
<h1 id="what-everyone-is-still-building"><strong>What Everyone Is Still Building</strong></h1>
<p>Claude Code exists. The MCP protocol exists. Power users are already interacting with SaaS products through AI agents — not because you built that integration, but because <em>they</em> built it themselves using whatever API you exposed. They’re writing <a href="https://lakshminp.substack.com/p/stop-making-claude-code-guess" rel="external nofollow noopener" class="lnp-link">CLAUDE.md files</a> that say “use the <a href="https://stacksweller.com/" rel="external nofollow noopener" class="lnp-link">Stacksweller</a> API to schedule posts” and just&hellip; doing it.</p>
<p>This is happening whether you designed for it or not.</p>
<p>The default SaaS in 2026 still ships dashboard-first: database → API → React. Users log in, stare at charts, try to draw conclusions. That model made sense when the only consumer of your product was a human looking at a screen.</p>
<p>That is no longer the only consumer of your product.</p>
<p>You can either build for this intentionally, or have it happen to you messily and then spend six months retrofitting.</p>
<h1 id="the-reframe"><strong>The Reframe</strong></h1>
<p>Here’s what x-intel actually looks like when you build it right:</p>
<p><strong>Intake</strong> — Claude asks who you are, what your niche is, what your X goals are, who your competitors are. You answer in plain English. Claude turns that into a structured profile using the <code>set_profile</code> tool.</p>
<p><strong>Baseline</strong> — Claude pulls your current stats, analyzes your last 90 tweets, benchmarks against competitors. All MCP tools calling your data layer. No UI step required.</p>
<p><strong>Strategy</strong> — Claude generates a content and growth plan: post frequency, best times, content formats, topics to lean into. Stored back in your database via MCP. The strategy exists before you’ve opened a browser.</p>
<p><strong>Periodic review</strong> — A cron job runs weekly analysis, compares performance against the strategy, surfaces what’s working and what isn’t. Claude writes a summary. The dashboard shows that summary.</p>
<p><strong>Course correction</strong> — Strategy updates based on data. Again, through tools. Again, before a human looks at anything.</p>
<p>The dashboard in this architecture isn’t the product. It’s an audit log. It shows you what Claude already figured out. Charts are passive — you still have to decide what to do. This tells you what to do, and then does it.</p>
<p>That’s a completely different product. “X-intel is your AI X strategist. Tell it your goals once. It watches your account, tracks competitors, and tells you exactly what to do next.”</p>
<p>That pitch destroys “SuperX but self-hosted.”</p>
<h1 id="how-to-actually-build-mcp-first"><strong>How to Actually Build MCP-First</strong></h1>
<p>The mechanics are simpler than they sound. Embarrassingly so.</p>
<p>Start by <a href="https://lakshminp.substack.com/p/mcp-server-tool-descriptions" rel="external nofollow noopener" class="lnp-link">designing your tools for Claude, not for humans</a>. Think about what Claude needs to do the job — not what a human wants to click on. Tool names, parameter shapes, return values should make sense to a language model. <code>get_competitor_engagement_trend(handle, days=30)</code> is better than <code>getChartData(config)</code>. One of these tells Claude what it’s getting. The other makes Claude guess.</p>
<p>Here’s the part nobody mentions: if you have a data layer, you have an MCP server 70% built already. Wrap your existing queries as tools. The MCP protocol is just a contract — your database doesn’t move.</p>
<p>You don’t need to build an “AI feature.” You need a <a href="https://lakshminp.substack.com/p/claude-code-prompt-engineering" rel="external nofollow noopener" class="lnp-link">system prompt that gives Claude the right context</a>, and tools that give it the right data. Claude is the strategist. Your MCP server is the strategist’s interface to your product. The actual work is thinking clearly about what Claude needs to know — not engineering.</p>
<p>Build the dashboard last, or thin. It’s a view layer. It shows stored strategies, weekly reviews, flagged anomalies. A log of decisions that were already made. Not a decision-support tool.</p>
<h1 id="one-build-two-audiences"><strong>One Build, Two Audiences</strong></h1>
<p>Here’s the payoff that makes this worth doing even if you don’t care about being “AI-native.”</p>
<p>A well-designed MCP server makes your product useful to two completely different types of users with almost no additional work.</p>
<p>The first type opens the dashboard, reads the weekly strategy review, clicks to approve the suggested changes, and closes the tab. Normal SaaS behavior. They don’t know or care that Claude is behind it. They just want outcomes.</p>
<p>The second type connects your MCP server to their own Claude Code setup, writes a <a href="http://claude.md/" rel="external nofollow noopener" class="lnp-link">CLAUDE.md</a> that describes how they want to use your product, and runs it themselves. These are your power users. They’ll do things with your product you never imagined, and they’ll tell everyone.</p>
<p>You still need the dashboard. Trials convert better with a UI. Not arguing otherwise. But the order matters: MCP layer first, dashboard second. The dashboard snaps on top in a weekend once the tools are solid. The reverse — retrofitting agent-friendly APIs onto a human-optimized interface — takes six months and still feels wrong.</p>
<p>Both audiences are real. Both are valuable. You get both by building the MCP layer correctly from the start, instead of bolting on an “AI integration” later when it’s expensive and awkward.</p>
<p>The dashboard-first founders will get there eventually. They’ll build the dashboard, grow slowly, and then spend six months retrofitting an API that was designed for human consumption into something an agent can actually use.</p>
<p>Or you build the MCP server first, ship a thin dashboard on top, and have both audiences from day one.</p>
<p>The dashboard ships itself. The strategist is Claude. The product is the tools you give it.</p>
<p>Stop building audit logs and calling them products.</p>
]]></content:encoded></item><item><title>While You Panic About AI Taking Jobs, I Built $200/Mo Tools</title><link>https://lakshminp.com/2026/02/stop-paying-ai-wrappers/</link><pubDate>Wed, 18 Feb 2026 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2026/02/stop-paying-ai-wrappers/</guid><category>essays</category><category>claude-code</category><category>saas</category><description>I was about to click “Subscribe: $29/month” on yet another AI content tool when I stopped.
Not because $29 was a lot. I’ve subscribed to worse. I have a graveyard of forgotten SaaS products auto-renewing somewhere in my credit card statement, silently draining money for tools I used exactly twice.
No, I stopped because I realized something embarrassing.
This tool was literally just a pretty wrapper around Claude. Same AI I already pay for. Same capabilities. They’d added a nice UI, a payment form, and approximately zero additional value.</description><content:encoded><![CDATA[<p>I was about to click “Subscribe: $29/month” on yet another AI content tool when I stopped.</p>
<p>Not because $29 was a lot. I’ve subscribed to worse. I have a graveyard of forgotten SaaS products auto-renewing somewhere in my credit card statement, silently draining money for tools I used exactly twice.</p>
<p>No, I stopped because I realized something embarrassing.</p>
<p>This tool was literally just a pretty wrapper around Claude. Same AI I already pay for. Same capabilities. They’d added a nice UI, a payment form, and approximately zero additional value.</p>
<p>I was about to pay $29/month to rent something I could build in an afternoon.</p>
<p>So I closed the tab. Opened Claude Code. And two hours later, I had my own version. No usage limits. No subscription. Mine forever.</p>
<p>That was six months ago. Since then, I’ve built six tools. I’ve eliminated $200/month in subscriptions. And I’ve realized something that changed how I think about this whole “AI is coming for your job” panic.</p>
<h1 id="everyones-worried-about-the-wrong-thing"><strong>Everyone’s Worried About the Wrong Thing</strong></h1>
<p>My LinkedIn feed is a horror show right now. Every other post is either “AI will take your job” or “Here’s how to survive the AI apocalypse” or some variation of “the robots are coming, repent.”</p>
<p>The advice is always the same. Learn to prompt. Adapt or die. Get your finances in order because disruption is coming.</p>
<p>Maybe it is. I don’t know the future any better than you do.</p>
<p>But here’s what I do know: while everyone’s stockpiling survival advice, I’ve been using those same AI tools to eliminate $200/month in software subscriptions. Tools I was paying for six months ago? I own them now. Forever. Zero recurring cost.</p>
<p>Same technology. Completely different mindset.</p>
<p>Let me show you what I mean.</p>
<h1 id="the-batch-pdf-processor-i-built-instead-of-uploading-50-files"><strong>The Batch PDF Processor I Built Instead of Uploading 50 Files</strong></h1>
<p>I had 50 research papers to process. Extract abstracts, pull out key findings, grab any data tables, save everything as searchable markdown.</p>
<p>Sure, Claude can read a PDF. One at a time. Upload, wait, copy the output, upload the next one, repeat 49 more times.</p>
<p>Old me would’ve done exactly that. Or Googled “batch PDF extraction tool,” found something that charges per page, done the math, decided it wasn’t worth it, and then manually uploaded 50 files anyway.</p>
<p>New me? I built a script.</p>
<p>Ninety minutes later, I had a skill that loops through a folder, extracts text and tables from each PDF using PyMuPDF, summarizes each one, and saves structured markdown files. Point it at a folder, go make coffee, come back to 50 organized summaries.</p>
<pre><code>&gt; Process all PDFs in ~/research/papers
[loops through 50 files]
[extracts + summarizes each]
[saves to ~/research/summaries/]
</code></pre>
<p>No uploading files one by one. No copy-paste marathon. No usage limits. Runs locally, so nothing leaves my machine.</p>
<p>The tool isn’t “PDF extraction”: Claude already does that. The tool is <em>automation</em>. Batch processing. The boring plumbing that turns a manual 3-hour task into a 5-minute one.</p>
<h1 id="the-video-transcription-pipeline-that-changed-how-i-learn"><strong>The Video Transcription Pipeline That Changed How I Learn</strong></h1>
<p>I’m an infoproduct junkie. Courses, masterclasses, workshops: if someone’s selling knowledge in video form, I’ve probably bought it. My Teachable and Gumroad purchase history is embarrassing. Hours and hours of content sitting in various dashboards, waiting to be watched.</p>
<p>Old me would take notes while watching. Pause, scribble, play, pause, scribble. Retain maybe 30% of it. Forget the rest within a week.</p>
<p>New me? I feed the videos to my video-distill skill. It transcribes everything with Whisper, distills it into readable chapters with Claude, and exports to EPUB.</p>
<p>Two hours of course video becomes a 12,000-word mini-book on my Kindle that I can search, highlight, and reference forever.</p>
<p>Build time: 2 hours.</p>
<p>Previous cost: $50-200 per course for transcription services (or just&hellip; not having transcripts and forgetting everything).</p>
<p>The ROI on courses went from “eh, probably worth it” to “this is a no-brainer.”</p>
<h1 id="the-pattern-nobody-wants-to-admit"><strong>The Pattern Nobody Wants to Admit</strong></h1>
<p>Here’s what I noticed while building these:</p>
<p><strong>Every AI SaaS is a thin wrapper around the same AI you already have access to.</strong></p>
<ul>
<li>
<p>Batch file processing? A loop + Claude.</p>
</li>
<li>
<p>Video transcription? Whisper + Claude.</p>
</li>
<li>
<p>Content research? Web fetch + Claude.</p>
</li>
<li>
<p>Cross-posting? Template formatting + Claude.</p>
</li>
<li>
<p>Writing assistant? Prompt engineering + Claude.</p>
</li>
</ul>
<p>The “product” is convenience packaging. A nice UI, hosting, a payment gateway, customer support. Sometimes that’s worth paying for.</p>
<p>But most of the time? You can build 80% of what you need in under two hours.</p>
<p>I’ve done this six times now. Total build time: about 14 hours. One weekend, spread across a few months.</p>
<p>Total monthly savings: $199.</p>
<p>Total annual savings: $2,388.</p>
<p>Tools I now own forever: 6.</p>
<h1 id="the-real-question-nobodys-asking"><strong>The Real Question Nobody’s Asking</strong></h1>
<p>While everyone argues about whether AI will take their job, here’s what I’m thinking:</p>
<p><strong>It’s not AI vs humans. It’s humans with AI vs humans without.</strong></p>
<p>The lawyer who refuses to use AI for contract review loses to the lawyer who uses it and handles 5x more clients.</p>
<p>The developer who doesn’t use AI for code generation loses to the developer who does and ships features in days instead of weeks.</p>
<p>The writer who thinks AI is “cheating” loses to the writer who uses it for research and drafts 10x more content.</p>
<p>The people who lose their jobs to AI won’t be the ones whose work AI can theoretically do.</p>
<p>They’ll be the ones who <em>didn’t use AI</em> and got outpaced by someone who did.</p>
<h1 id="what-i-actually-do-instead-of-panicking"><strong>What I Actually Do Instead of Panicking</strong></h1>
<p>I audit my subscriptions. Every few months, I go through my recurring charges and ask: “Is this just an AI wrapper?”</p>
<p>If yes, I build a replacement. If the replacement covers 80% of my use cases, I cancel the subscription.</p>
<p>Here’s my current hit list:</p>
<ul>
<li>
<p><strong>Batch PDF processing</strong>: replaced manual uploads with pdf-reader skill (90 min)</p>
</li>
<li>
<p><strong>Video transcription</strong>: replaced $50-200/course services with video-distill skill (2 hours)</p>
</li>
<li>
<p><strong>Ebook formatting</strong>: replaced $30/book services with epub-builder skill (1 hour)</p>
</li>
<li>
<p><strong>Content research</strong>: replaced $29/mo tools with compose skill (3 hours)</p>
</li>
<li>
<p><strong>Cross-posting</strong>: replaced $50/mo tools with distribute skill (2 hours)</p>
</li>
<li>
<p><strong>Writing assistant</strong>: replaced $20/mo Sudowrite etc with fiction-writer skill (4 hours)</p>
</li>
</ul>
<p>Not everything is worth building. QuickBooks? Keep paying. Complex Zapier automation with 50 integrations? Probably keep paying. Hosted databases? Definitely keep paying.</p>
<p>But simple AI wrappers that just call Claude with a prompt and charge you monthly for it? Those are dying. You can own that.</p>
<h1 id="this-is-what-leverage-actually-looks-like"><strong>This Is What Leverage Actually Looks Like</strong></h1>
<p>When you own your tools, you can modify them to fit your exact workflow. Combine them in ways SaaS products can’t. Build competitive advantages nobody else has.</p>
<p>My <code>distribute</code> skill cross-posts to five platforms in one command. Most people manually post to each: different formatting, different copy, different everything. That’s 30 minutes per post. I do it in 2 minutes.</p>
<p>Over a year, that’s 50+ hours saved. For one skill.</p>
<p>My <code>video-distill</code> skill turns courses into searchable mini-books. Most people watch courses once and forget 80% of it. I have permanent reference material I can search and review anytime.</p>
<p>This is how one-person operations beat ten-person teams. Not by working harder. By owning tools that make you 10x faster.</p>
<h1 id="two-paths"><strong>Two Paths</strong></h1>
<p>The AI revolution is here. Not coming. Here.</p>
<p><strong>Path A:</strong> Read about how AI is going to disrupt your career. Worry about it. Prepare for the worst. Maybe it happens, maybe it doesn’t. Either way, you spent months anxious instead of building.</p>
<p><strong>Path B:</strong> Use AI to eliminate expenses, build tools, ship faster, own your stack. If disruption comes, you’re already leveraged. If it doesn’t, you still saved $2,400/year and got 10x faster.</p>
<p>I’m on Path B.</p>
<p>I built six skills in 14 hours. I save $200/month. I own tools that do exactly what I need, with no usage limits, no pricing tiers, and no risk of some startup getting acqui-hired and shutting down my workflow.</p>
<p>And I’m shipping four SaaS products while working two day jobs, because I have the leverage to do it.</p>
<p>You can panic, or you can build.</p>
<p>I’m building.</p>
<h1 id="if-you-want-to-start"><strong>If You Want to Start</strong></h1>
<p>Here’s the playbook I use every time.</p>
<h2 id="step-1-pick-your-target"><strong>Step 1: Pick Your Target</strong></h2>
<p>Start with something you use weekly but don’t need enterprise features for. The sweet spot is tools where you’re paying for convenience, not capability.</p>
<p><strong>Good first targets:</strong></p>
<ul>
<li>
<p>Batch processing workflows (loop through files, process each, save outputs)</p>
</li>
<li>
<p>Video/audio transcription (Whisper is free and runs locally)</p>
</li>
<li>
<p>Content research and brainstorming (web scraping + Claude)</p>
</li>
<li>
<p>Grammar/style checking (Claude prompts replace Grammarly)</p>
</li>
<li>
<p>Format conversion pipelines (markdown → EPUB, video → transcript → summary)</p>
</li>
</ul>
<p><strong>Bad first targets:</strong></p>
<ul>
<li>
<p>Accounting software (compliance, integrations, audit trails)</p>
</li>
<li>
<p>Complex multi-step automation with 20+ triggers</p>
</li>
<li>
<p>Anything requiring hosted infrastructure you don’t want to manage</p>
</li>
<li>
<p>Real-time collaboration tools (Google Docs, Figma)</p>
</li>
</ul>
<h2 id="step-2-describe-the-workflow-not-the-tool"><strong>Step 2: Describe the Workflow, Not the Tool</strong></h2>
<p>Don’t say “build me a transcription tool.” Say “I have 20 course videos. I want to transcribe each one, distill the key points, and save them as markdown files organized by chapter.”</p>
<p>The more specific you are about your <em>actual workflow</em>, the better the tool fits. You’re not building a generic SaaS: you’re building exactly what you need.</p>
<h2 id="step-3-start-ugly-iterate-fast"><strong>Step 3: Start Ugly, Iterate Fast</strong></h2>
<p>Your first version will be rough. That’s fine.</p>
<p>My video transcription pipeline started as a janky script that choked on long files. I fixed the edge cases as I hit them. Now it handles 3-hour lectures without breaking a sweat.</p>
<p>Don’t try to build the polished SaaS version. Build the “works for my specific use case” version. That takes 90 minutes, not 90 days.</p>
<h2 id="step-4-the-80-test"><strong>Step 4: The 80% Test</strong></h2>
<p>Run your homegrown tool alongside the paid one for 30 days. Track when you reach for the paid tool instead.</p>
<p>If your skill handles 80% of cases, cancel the subscription. The remaining 20%? Either iterate on your skill or accept the occasional manual workaround.</p>
<p>Perfect is the enemy of $X/month forever.</p>
<h2 id="step-5-compound-it"><strong>Step 5: Compound It</strong></h2>
<p>Once you’ve built one, you’ll notice patterns. The same techniques: file handling, API calls, text processing, output formatting: show up everywhere.</p>
<p>Your second skill takes half the time. Your fifth takes 20 minutes.</p>
<p>This is how you end up owning your entire stack without spending months building it.</p>
<h2 id="the-prompt-that-starts-everything"><strong>The Prompt That Starts Everything</strong></h2>
<p>If you’re using Claude Code or similar:</p>
<pre><code>I want to build a tool that [specific workflow].
I currently do this by [current manual process or paid tool].
My input is [what you're working with].
I want the output to be [format and destination].
What's the simplest way to build this?
</code></pre>
<p>Then iterate. The AI will ask clarifying questions, suggest approaches, write code. You test, refine, test again.</p>
<p>Two hours later, you own something you would’ve rented forever.</p>
<p>The people who win the next decade won’t be the ones who worried about AI disruption.</p>
<p>They’ll be the ones who used AI to build tools, eliminate costs, and move faster than everyone else.</p>
<p>Don’t rent your stack. Own it.</p>
<p><em>P.S.: The AI wrapper economy is dying. Every “AI-powered” tool that’s just a UI around Claude or GPT is on borrowed time. The moment users realize they can build 80% of that themselves, the subscription revenue evaporates. If you’re building an AI SaaS, make sure your value is in the 20% that can’t be replicated in two hours.</em></p>
]]></content:encoded></item><item><title>The Real SaaS Moat AI Can't Replicate</title><link>https://lakshminp.com/2026/02/ai-saas-moat-exposed/</link><pubDate>Mon, 09 Feb 2026 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2026/02/ai-saas-moat-exposed/</guid><category>essays</category><category>saas</category><description>There’s a comment buried 14 levels deep in this Hacker News thread about AI killing B2B SaaS. It has 37 upvotes and it’s the smartest thing I’ve read this year.
Here it is, paraphrased: “The real innovation of SaaS was laundering inaccessible open-source software into a format that doesn’t require transiting git. The hard part was never the code. The hard part was that git sucks.”
I laughed. Then I stopped laughing because it’s devastatingly correct.</description><content:encoded><![CDATA[<p>There’s a comment buried 14 levels deep in <a href="https://news.ycombinator.com/item?id=46888441" rel="external nofollow noopener" class="lnp-link">this Hacker News thread about AI killing B2B SaaS</a>. It has 37 upvotes and it’s the smartest thing I’ve read this year.</p>
<p>Here it is, paraphrased: “The real innovation of SaaS was laundering inaccessible open-source software into a format that doesn’t require transiting git. The hard part was never the code. The hard part was that git sucks.”</p>
<p>I laughed. Then I stopped laughing because it’s devastatingly correct.</p>
<h2 id="the-git-laundering-machine"><strong>The Git Laundering Machine</strong></h2>
<p>Think about the most profitable SaaS businesses in technology. Seriously, list them.</p>
<p>AWS? That’s Linux, KVM, and Xen behind a billing dashboard. Heroku was git-push-to-deploy because deploying was too hard. Vercel is the same thing for Next.js. MongoDB Atlas is MongoDB without the ops. Redis Cloud is Redis without the YAML. Supabase is Postgres without the DBA.</p>
<p>Every single one of them is a factory that converts something freely available on GitHub into something you can pay for on a website.</p>
<p>The commenter was right. These companies didn’t build moats with proprietary technology. They built moats by standing between users and git. Their value proposition, stripped to the studs, is: “You don’t have to clone a repo.”</p>
<p>That’s a $500 billion industry built on the fact that <code>git clone</code> is scary.</p>
<h2 id="llms-just-killed-the-middleman"><strong>LLMs Just Killed the Middleman</strong></h2>
<p>Here’s where the “AI is killing SaaS” thesis gets real.</p>
<p>When a CTO says “can we build this internally?”, the old answer was: “Technically yes, but you’d need 3 engineers, 6 months, and ongoing maintenance. Just buy the SaaS.”</p>
<p>The new answer: “ChatGPT set it up in 20 minutes. It reads from the same open-source code the SaaS vendor uses. It runs on our infrastructure. There’s no monthly bill.”</p>
<p>LLMs do exactly what SaaS companies do — they take inaccessible open-source software and make it usable by normal humans. They just skip the subscription.</p>
<p>The git laundering machine now has competition. And the competitor works for free.</p>
<h2 id="what-actually-survives"><strong>What Actually Survives</strong></h2>
<p>So is B2B SaaS dead? No. But the moat map just got redrawn.</p>
<p>Here’s what doesn’t survive: <strong>any SaaS whose primary value is “we set it up so you don’t have to.”</strong> Deployment wrappers, config GUIs, managed hosting for commodity databases — all of this is getting compressed.</p>
<p>An HN commenter who manages teams put it bluntly: “Management doesn’t want to be responsible for bespoke internal tools.” That’s real. But it’s a shrinking moat. Today’s management doesn’t want to be responsible. Tomorrow’s management grew up with ChatGPT and doesn’t see internal tooling as risky.</p>
<p>Here’s what survives:</p>
<p><strong>Data.</strong> If your SaaS accumulates proprietary data over time — customer behavior patterns, industry benchmarks, network effects — that’s a moat AI can’t replicate. A new LLM-generated tool starts with zero data. Your SaaS has three years of it.</p>
<p><strong>Compliance and trust.</strong> SOC 2, HIPAA, GDPR certification takes time and money. “ChatGPT built it” doesn’t pass an enterprise security audit. Yet.</p>
<p><strong>Workflow lock-in.</strong> Not the software itself, but the habits. Slack isn’t hard to replace technically. It’s hard to replace because your whole company’s muscle memory lives there.</p>
<p><strong>Network effects.</strong> Figma isn’t valuable because of the rendering engine. It’s valuable because your designers, developers, and product managers are all in the same file. That’s a moat no amount of vibe coding can replicate.</p>
<p><strong>The specification itself.</strong> Here’s the contrarian take within the contrarian take: as code becomes commodity, the spec becomes the product. The companies that survive aren’t the ones that write the best code. They’re the ones that understand the problem deeply enough to specify what “right” looks like. Everyone else is just a GPT wrapper with a landing page.</p>
<h2 id="the-indie-saas-playbook-changes"><strong>The Indie SaaS Playbook Changes</strong></h2>
<p>If you’re building SaaS solo — and if you’re reading this newsletter, you probably are — the implications are brutal and clear.</p>
<p><em>Full disclosure: I built a product that does exactly this. <a href="https://supabyoi.com/" rel="external nofollow noopener" class="lnp-link">Supabyoi</a> deploys Supabase for you. By my own thesis, that’s a shrinking moat. I’m writing this post partly because I’m living the question: evolve or get compressed.</em></p>
<p><strong>Stop building tools. Start building data flywheels.</strong></p>
<p>A CRUD app with a nice UI is now a weekend project for anyone with ChatGPT. A system that gets smarter with every user interaction is still a real business.</p>
<p><strong>Stop selling setup. Start selling ongoing value.</strong></p>
<p>“We deploy Postgres for you” is dying. “We analyze your Postgres performance patterns across 10,000 databases and tell you what’s about to break” is thriving.</p>
<p><strong>Stop competing on features. Start competing on understanding.</strong></p>
<p>The SaaS products that survive AI commodification will be the ones that understand their customers’ problems better than a general-purpose LLM ever could. Domain expertise is the last moat.</p>
<h2 id="the-500-billion-question"><strong>The $500 Billion Question</strong></h2>
<p>The HN thread devolved into the usual “AI is overhyped” vs. “AI changes everything” tribal warfare. But that one comment, buried 14 levels deep, cut through all of it.</p>
<p>The SaaS moat was never the software. It was the fact that software was hard to access. That moat is evaporating.</p>
<p>What’s left is data, trust, network effects, and deep domain understanding.</p>
<p>Build your SaaS around those. Or enjoy competing with a free chatbot.</p>
]]></content:encoded></item><item><title>I Built 2 SaaS Products Vibe Coding. Here's the System That Made It Work.</title><link>https://lakshminp.com/2026/01/vibe-coding-2-saas-products/</link><pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2026/01/vibe-coding-2-saas-products/</guid><category>essays</category><category>saas</category><category>ai-coding</category><description>Gene Kim and Steve Yegge’s Vibe Coding book says you’re the head chef now.
The metaphor runs through the whole thing: you’re not a line cook anymore, you’re orchestrating AI sous chefs, directing the kitchen, tasting every dish before it goes out. The developer-as-implementer era is over. Welcome to developer-as-orchestrator.
The Biryani Incident It’s a good metaphor. I buy it. But here’s the thing about being a head chef that the metaphor doesn’t quite capture: a head chef without mise en place is just a guy having a panic attack near hot surfaces.</description><content:encoded><![CDATA[<p>Gene Kim and Steve Yegge’s <a href="https://www.amazon.com/Vibe-Coding-Building-Production-Grade-Software/dp/1966280025" rel="external nofollow noopener" class="lnp-link">Vibe Coding</a> book says you’re the head chef now.</p>
<p>The metaphor runs through the whole thing: you’re not a line cook anymore, you’re orchestrating AI sous chefs, directing the kitchen, tasting every dish before it goes out. The developer-as-implementer era is over. Welcome to developer-as-orchestrator.</p>
<h2 id="the-biryani-incident"><strong>The Biryani Incident</strong></h2>
<p>It’s a good metaphor. I buy it. But here’s the thing about being a head chef that the metaphor doesn’t quite capture: a head chef without mise en place is just a guy having a panic attack near hot surfaces.</p>
<p>I know this because I’ve been that guy. Literally.</p>
<p>My wife had to leave town for a few days. “I’ll handle dinner,” I said, with the confidence of someone who has watched many cooking videos and successfully boiled pasta multiple times. I decided to make veg biryani — a dish my wife makes effortlessly, layering rice and vegetables and spices into something that tastes like it required more effort than it actually did.</p>
<p>“Prep everything first,” she told me before leaving. “Soak the basmati rice. Marinate the paneer. Chop the vegetables for layering. Have it all ready before you start cooking.”</p>
<p>Reader, I did not do this.</p>
<p>I started frying onions. While the onions were going, I realized I hadn’t marinated the paneer. So I started cubing paneer and mixing yogurt and spices. Then the onions started burning. I ran back, stirred frantically, ran back to the paneer. Remembered I needed to soak the basmati. Started the rice soaking. The onions were now definitely burned. I scraped them out, started over, but now I was behind, so I tried to do the vegetables and the new onions simultaneously while the paneer sat half-marinated&hellip;</p>
<p>An hour later I had a kitchen that looked like a crime scene, three pans with various stages of failure in them, and something that was technically edible but bore no resemblance to biryani. My wife, via video call, watched me plate this disaster with the expression of someone who had specifically warned against this exact outcome.</p>
<p>The problem wasn’t skill. I can cook. The problem was that prep and execution were bleeding into each other. I was trying to figure out what I needed while also doing the thing. And it turns out you can’t actually do both. Not well, anyway.</p>
<p>I’ve been that guy with AI sous chefs too.</p>
<p>I’ve been vibe coding since mid-2025. By “vibe coding” I mean the thing where you describe what you want in natural language and an AI writes the code. You know, the future we were promised, except the future has some sharp edges nobody mentioned in the demos.</p>
<p>Two SaaS products. Real users. Real revenue. Not toy projects, not “look ma I generated a todo app” tutorials, not the kind of thing you show off on Twitter and then quietly delete three weeks later. Actual products that people pay actual money for.</p>
<p>So when I tell you what follows, understand: this isn’t theory. This is what I learned by shipping real things and watching everything that could go wrong go wrong.</p>
<h2 id="the-markdown-hemorrhage"><strong>The Markdown Hemorrhage</strong></h2>
<p>For the first few months, I was that chef.</p>
<p>I’d sit down to implement a feature. Claude and I would get rolling. Then I’d notice a bug. Well, I’m already here, might as well fix the bug. Then while fixing the bug, I’d realize the error handling was inconsistent. Better clean that up. Oh, and there’s still context left in the window — might as well tackle that other feature I’ve been meaning to add.</p>
<p>Two hours later: three half-finished things, Claude confused about which task we’re actually doing, and code quality somewhere between “works” and “I’m not sure why.”</p>
<p>And the markdown. God, the markdown.</p>
<p>Claude, bless its heart, wanted to help me remember things. So it started creating files. <a href="http://architecture.md/" rel="external nofollow noopener" class="lnp-link">ARCHITECTURE.md</a>. <a href="http://decisions.md/" rel="external nofollow noopener" class="lnp-link">DECISIONS.md</a>. IMPLEMENTATION_NOTES.md. <a href="http://todo.md/" rel="external nofollow noopener" class="lnp-link">TODO.md</a>. <a href="http://context.md/" rel="external nofollow noopener" class="lnp-link">CONTEXT.md</a>. <a href="http://changelog.md/" rel="external nofollow noopener" class="lnp-link">CHANGELOG.md</a>. README_UPDATED.md.</p>
<p>I call this markdown hemorrhage. The AI equivalent of a kitchen where every surface is covered with prep bowls, half-chopped vegetables, and sticky notes that say “DON’T FORGET THE SAUCE” — technically documentation, practically chaos.</p>
<p>At one point I had so many markdown files that I needed another AI tool just to search through the documentation I’d created for my AI tool.</p>
<p>This was clearly insane.</p>
<p>But here’s the thing that took me embarrassingly long to figure out: the problem wasn’t the tools. The problem was me.</p>
<h2 id="one-goal-per-session"><strong>One Goal Per Session</strong></h2>
<p>I was treating every Claude session like a buffet.</p>
<p>You know how it goes. You sit down to implement a feature. While you’re implementing, you notice a bug. Well, you’re already here, might as well fix the bug. Oh, and while fixing the bug, you realize the error handling is inconsistent across the codebase. Better clean that up too. And hey, there’s still context left in the window — might as well tackle that other feature you’ve been meaning to add.</p>
<p>Two hours later, you’ve got three half-finished things, Claude is confused about which task it’s actually working on, and the code quality has degraded to “works but I’m not sure why.”</p>
<p>I call this context pollution. And once I named it, I started seeing it everywhere.</p>
<p>LLMs are bad at juggling multiple goals. This isn’t a Claude problem — it’s a fundamental thing about how these models work. When you ask them to hold multiple objectives simultaneously, they get worse at all of them. Not a little worse. <em>Dramatically</em> worse.</p>
<p>The fix sounds almost stupidly simple: one goal per session.</p>
<p>That’s it. That’s the whole trick. One goal. One session. If you discover a bug while implementing a feature, you write down the bug and you close the session. The bug gets its own session later. No “while I’m here” detours. No context pollution.</p>
<p>“But what about efficiency?” I hear you asking. “Isn’t it wasteful to end a session when there’s still context left?”</p>
<p>This is the trap. This is exactly the thinking that leads to burned onions and half-marinated paneer. The leftover context is not an asset. It’s a liability. It’s your coworker with three tasks open, doing all of them poorly, about to forget everything anyway.</p>
<p>End the session. Start fresh. One goal.</p>
<h2 id="the-mise-en-place"><strong>The Mise en Place</strong></h2>
<p>Now, this discipline only works if you have a way to track what you’re not doing.</p>
<p>If you end a session every time you discover a bug, you need somewhere for that bug to live. Otherwise you’ll forget it. The bugs pile up in your head, you context-switch mentally, and you’re back where you started.</p>
<p>This is where beads comes in.</p>
<p>Beads is a git-backed issue tracker that Claude can read and write. Steve Yegge built it (yes, that Steve Yegge — the guy who wrote the platforms rant and approximately nine million words about Emacs). The idea is simple: every task becomes a “bead.” Claude creates them, updates them, closes them. They survive compaction. They sync through git.</p>
<p>I installed it. I ran <code>bd init</code>. And then something clicked.</p>
<p>See, beads isn’t just a todo list. It’s a forcing function. When you start a session, you run <code>bd ready</code> and it shows you what’s available to work on. You pick <em>one</em>. Not three. One.</p>
<p>And when you discover a bug mid-session? You tell Claude to create a bead for it. Claude writes it down, logs the context, notes any relevant details. Then you move on. The bug exists now. It has a home. You don’t have to hold it in your head.</p>
<p>The discipline and the tool reinforce each other. One bead per session only works because beads exist to capture everything else. And beads only work because the discipline prevents you from drowning in them.</p>
<h2 id="grooming-vs-coding"><strong>Grooming vs. Coding</strong></h2>
<p>But I’m getting ahead of myself. Let me tell you about grooming.</p>
<p>In my old workflow, I’d sit down and just&hellip; start. Open Claude, describe what I wanted, begin coding. Very vibe. Very chaotic. Whatever felt right in the moment.</p>
<p>The problem is that “figuring out what to do” and “doing the thing” are completely different cognitive modes. One is divergent — you’re exploring possibilities, breaking down problems, identifying edge cases. The other is convergent — you’re executing, making decisions, writing code.</p>
<p>When you mix them, you get mush.</p>
<p>So now I run two types of sessions:</p>
<p>Grooming sessions are for thinking. I’m not coding. I’m not even planning to code in this session. I’m creating beads. Breaking down a feature into pieces. Identifying dependencies. Noting edge cases. If I think of an unrelated feature while grooming, it gets written down — for a different grooming session. No cross-contamination.</p>
<p>Coding sessions are for execution. One bead. Implement it. If I discover a bug, I note it and keep going unless it’s blocking. The bug gets groomed and coded in its own sessions later.</p>
<p>This separation is the whole game. It sounds bureaucratic. It sounds like exactly the kind of process that “vibe coding” was supposed to eliminate. But here’s the secret: this discipline is what makes vibe coding actually work at scale. Without it, you’re just generating code and hoping. With it, you’re building systems.</p>
<h2 id="a-few-other-things"><strong>A Few Other Things</strong></h2>
<p>MCPs should be loaded at project level, not globally. Every MCP eats context. If a project doesn’t need the Reddit MCP, it doesn’t get the Reddit MCP. Context is expensive. Guard it like it’s money, because in a very real sense, it is.</p>
<p>Autocompact should be off. I want to control when context resets, not have the algorithm decide for me mid-feature. Yes, this means manually managing sessions. That’s the point.</p>
<p><a href="http://claude.md/" rel="external nofollow noopener" class="lnp-link">Claude.md</a> files are more powerful than you think. I have a global one in <code>~/.claude/CLAUDE.md</code> with rules that apply everywhere. Each project gets its own with project-specific instructions. Claude reads these automatically. They’re like a pre-prompt that doesn’t eat your context window.</p>
<h2 id="what-still-doesnt-work"><strong>What Still Doesn’t Work</strong></h2>
<p>Now, here’s the part where I’m supposed to tell you it’s all solved and my workflow is perfect.</p>
<p>It’s not.</p>
<p>Debugging production issues is still clunky. I’ve got a combination of skills and MCPs that sort of works, but there’s too much manual context assembly. Something breaks in prod and I’m still spending the first 20 minutes of the session explaining the architecture before we can even start diagnosing.</p>
<p>Test-driven development doesn’t flow. The loop of “write test, see it fail, implement, see it pass” — it’s awkward. Claude wants to write everything at once. I’m still tweaking my tooling to make TDD feel natural.</p>
<p>UX work is hard. Like, fundamentally hard. Claude can scaffold UI. It can generate components. But “does this feel right?” is a human judgment call, and trying to get there through text-based iteration is like describing a painting to someone and asking them to tell you if it’s beautiful.</p>
<p>These are the walls I’m hitting. I’m building tooling to address them — an <a href="https://lakshminp.substack.com/p/why-im-building-an-agent-orchestrator" rel="external nofollow noopener" class="lnp-link">agent orchestrator</a> that tailors Claude to my specific workflow. Work in progress. If you’re the adventurous type, you can <a href="https://badri.github.io/wt/" rel="external nofollow noopener" class="lnp-link">try it now</a>.</p>
<h2 id="the-system"><strong>The System</strong></h2>
<p>So here’s the actual system, if you want to try it:</p>
<ol>
<li>
<p>Install beads: <code>npm install -g @anthropic-ai/beads &amp;&amp; bd init</code></p>
</li>
<li>
<p>Add to your global <a href="http://claude.md/" rel="external nofollow noopener" class="lnp-link">CLAUDE.md</a>: “Check <code>bd ready</code> at session start. One bead per session.”</p>
</li>
<li>
<p>Separate grooming from coding. Different sessions. Different mindsets.</p>
</li>
<li>
<p>Resist the urge to “do more while there’s context left.” That’s the trap.</p>
</li>
<li>
<p>Protect your context. Project-level MCPs only. Kill anything you don’t need.</p>
</li>
</ol>
<p>Two SaaS products since mid-2025. All vibe coded with this system.</p>
<p>Not because the tools are magic. The tools are good, but tools are never magic. What made it work was the discipline — the willingness to be a little bit boring about context hygiene, to resist the temptation to do more, to trust that a focused session ships more than a scattered one.</p>
<p>Vibe coding without chaos. It turns out it’s not about vibing harder. It’s about vibing deliberately.</p>
<p>You’re the head chef now. But don’t forget your mise en place.</p>
<p>My wife was right, by the way. She usually is.</p>
<p><em>I’m Lakshmi. 20 years in software — ops, infrastructure, full-stack. Now solo founder using Claude Code to develop, deploy, and distribute.</em></p>
]]></content:encoded></item><item><title>The $30/Year Stack for Launching Small Bets</title><link>https://lakshminp.com/2026/01/30-dollar-saas-stack/</link><pubDate>Mon, 19 Jan 2026 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2026/01/30-dollar-saas-stack/</guid><category>essays</category><category>saas</category><category>kubernetes</category><description>Every time I launch a new small bet, I need the same boring stuff: professional email, a chat widget, uptime monitoring. The kind of infrastructure that’s completely unsexy but makes you look like you have your act together.
For years, I overcomplicated this. Custom SMTP servers. Self-hosted monitoring. Elaborate setups that took days to configure and broke whenever I looked at them wrong.
Then I realized something: I was spending more time on infrastructure than on validating whether anyone wanted my product.</description><content:encoded><![CDATA[<p>Every time I launch a new small bet, I need the same boring stuff: professional email, a chat widget, uptime monitoring. The kind of infrastructure that’s completely unsexy but makes you look like you have your act together.</p>
<p>For years, I overcomplicated this. Custom SMTP servers. Self-hosted monitoring. Elaborate setups that took days to configure and broke whenever I looked at them wrong.</p>
<p>Then I realized something: I was spending more time on infrastructure than on validating whether anyone wanted my product.</p>
<p>So I built a repeatable stack. Total cost: about $30-42 per year, per small bet. Here’s the whole thing.</p>
<h2 id="domain--hosting-cloudflare-free"><strong>Domain &amp; Hosting: Cloudflare (Free)</strong></h2>
<p>Buy your domain wherever you want, but point the nameservers to Cloudflare immediately.</p>
<p>Cloudflare’s free tier is absurd:</p>
<ul>
<li>
<p>DNS management (fast, reliable)</p>
</li>
<li>
<p>Free SSL certificates (automatic)</p>
</li>
<li>
<p>DDoS protection</p>
</li>
<li>
<p>CDN caching</p>
</li>
<li>
<p>Cloudflare Pages (unlimited sites, unlimited bandwidth)</p>
</li>
</ul>
<p>That last one is key. Your landing page goes on Cloudflare Pages. Connect your repo, push to main, it deploys. No servers. No bills. No thinking about infrastructure when you should be thinking about whether anyone wants your product.</p>
<p>I run every small bet’s landing page on CF Pages. Zero hosting cost.</p>
<h2 id="email-google-workspace-the-india-pricing-hack"><strong>Email: Google Workspace (The India Pricing Hack)</strong></h2>
<p>You want professional email. <code>hello@yourdomain.com</code>, not <code>yourdomain.help@gmail.com</code> like some kind of digital nomad running a dropshipping scam.</p>
<p>Google Workspace direct pricing: $6/month. Painful when you’re running multiple bets.</p>
<p>Google Workspace through an Indian reseller: Rs.125/month. That’s roughly $1.50.</p>
<p>Same product. Same Gmail experience. Same everything. Just&hellip; cheaper, because regional pricing exists and Google apparently forgot to close this loophole.</p>
<p>Recommended resellers: Medha Cloud, Host IT Smart, Shivaami. They’re authorized, they’re legit, and they’ll save you $50+/year per domain.</p>
<p>Setup takes 30 minutes: verify domain, add MX records, configure SPF/DKIM/DMARC so your emails don’t land in spam. Done.</p>
<h2 id="support-crisp-chat-free"><strong>Support: Crisp Chat (Free)</strong></h2>
<p>Intercom wants $74/month. For a small bet that might make $0.</p>
<p>Crisp’s free tier gives you:</p>
<ul>
<li>
<p>2 team seats (it’s just you anyway)</p>
</li>
<li>
<p>Unlimited conversations</p>
</li>
<li>
<p>Mobile app for notifications</p>
</li>
<li>
<p>A widget that doesn’t look like it was designed in 2008</p>
</li>
</ul>
<p>Copy-paste their script tag into your landing page. Five minutes.</p>
<p>Upgrade trigger: when you have so many support conversations that you need automation. Which means you have customers. Which means you can afford to pay for things.</p>
<h2 id="monitoring-betterstack-free"><strong>Monitoring: BetterStack (Free)</strong></h2>
<p>Your app will go down at 3am on a Sunday. This is not a prediction, it’s a guarantee.</p>
<p>BetterStack’s free tier:</p>
<ul>
<li>
<p>10 uptime monitors</p>
</li>
<li>
<p>1GB logs/month</p>
</li>
<li>
<p>Email and Slack alerts</p>
</li>
<li>
<p>3-day log retention</p>
</li>
</ul>
<p>Is 3-day retention enough? For a small bet you’re validating? Yes. You’re not running a bank.</p>
<p>Alternative: Axiom gives you 500GB ingest and 30-day retention if you’re logging more aggressively. Also free.</p>
<h2 id="error-tracking-sentry-free"><strong>Error Tracking: Sentry (Free)</strong></h2>
<p>Your code will throw exceptions in production that never happened locally. Classic.</p>
<p>Sentry’s free tier:</p>
<ul>
<li>
<p>5K errors/month</p>
</li>
<li>
<p>10K performance transactions</p>
</li>
<li>
<p>1 user</p>
</li>
<li>
<p>90-day retention</p>
</li>
</ul>
<p>For a small bet, 5K errors/month is plenty. If you’re hitting that limit, either your app is broken or you have enough users to pay for it.</p>
<h2 id="database-supabase-free-tier-or-self-hosted"><strong>Database: Supabase (Free Tier or Self-Hosted)</strong></h2>
<p>Every small bet needs a database. Supabase’s free tier is genuinely useful:</p>
<ul>
<li>
<p>500MB database</p>
</li>
<li>
<p>1GB file storage</p>
</li>
<li>
<p>50K monthly active users</p>
</li>
<li>
<p>Unlimited API requests</p>
</li>
</ul>
<p>That’s enough to validate most ideas. The catch: you get 2 free projects total. After that, it’s $25/month per project.</p>
<p>For small bets that graduate to real products, I self-host Supabase on a $6/month Hetzner VPS. Full Postgres, auth, storage, realtime — no project limits, no usage caps. (I’m building a service called <a href="https://supabyoi.com/" rel="external nofollow noopener" class="lnp-link">Supabyoi</a> to make this dead simple. More on that soon.)</p>
<h2 id="the-complete-stack"><strong>The Complete Stack</strong></h2>
<ul>
<li>
<p><strong>Domain</strong> — ~$10-15/year</p>
</li>
<li>
<p><strong>Cloudflare (DNS + Pages)</strong> — Free</p>
</li>
<li>
<p><strong>Google Workspace (India)</strong> — ~1.50/month( 1.50/<em>month</em>( 18/year)</p>
</li>
<li>
<p><strong>Crisp</strong> — Free</p>
</li>
<li>
<p><strong>BetterStack</strong> — Free</p>
</li>
<li>
<p><strong>Sentry</strong> — Free</p>
</li>
<li>
<p><strong>Supabase</strong> — Free</p>
</li>
</ul>
<p><strong>Total: ~1.50/month, 1.50/<em><strong><strong>month</strong></strong></em>, 30-42/year</strong></p>
<p>That’s DNS, hosting, professional email, live chat, uptime monitoring, error tracking, and a database for less than a single month of most “startup” tools.</p>
<h2 id="the-rules"><strong>The Rules</strong></h2>
<p><strong>Don’t upgrade until you have paying customers.</strong> Free tiers exist for validation. Use them.</p>
<p><strong>Keep the setup identical across bets.</strong> Same tools, same patterns, same DNS records. You should be able to launch a new bet’s infrastructure in an afternoon, not a weekend.</p>
<p><strong>Resist the urge to self-host.</strong> Yes, you <em>can</em> run your own mail server. You can also perform your own dental surgery. Neither is advisable.</p>
<h2 id="when-to-actually-upgrade"><strong>When To Actually Upgrade</strong></h2>
<ul>
<li>
<p><strong>Google Workspace</strong> — You need &gt;30GB storage → $7/mo</p>
</li>
<li>
<p><strong>Crisp</strong> — You need chatbots or &gt;2 team members → $25/mo</p>
</li>
<li>
<p><strong>BetterStack</strong> — You’re pushing &gt;1GB logs/month → $24/mo</p>
</li>
<li>
<p><strong>Sentry</strong> — You’re hitting 5K errors/month → $26/mo</p>
</li>
<li>
<p><strong>Supabase</strong> — You need &gt;2 projects or more storage → $25/mo (or self-host)</p>
</li>
</ul>
<p>Notice a pattern? These are all “you have real traction” problems. Good problems to have.</p>
<h2 id="whats-not-covered-yet"><strong>What’s Not Covered (Yet)</strong></h2>
<p>This is the skeleton — the basic infrastructure every small bet needs from day one.</p>
<p>I’ll cover these in separate posts:</p>
<ul>
<li>
<p><strong>Tech stack choices</strong> (frameworks, languages, deployment)</p>
</li>
<li>
<p><strong>Payment processing</strong> (Stripe, Lemon Squeezy, regional considerations)</p>
</li>
<li>
<p><strong>CI/CD pipelines</strong> (GitHub Actions, deployment automation)</p>
</li>
<li>
<p><strong>Landing page patterns</strong> (what actually converts)</p>
</li>
</ul>
<p>One thing at a time.</p>
<h2 id="the-point"><strong>The Point</strong></h2>
<p>Infrastructure should be invisible. It should cost almost nothing while you’re validating. It should scale up only when you have revenue to pay for it.</p>
<p>$30/year per bet means you can run 10 small bets for less than most people pay for a single Notion subscription.</p>
<p>Stop building infrastructure. Start shipping products.</p>
<p><em>This is part of my “Deploy” series — simple infrastructure patterns for solo operators who’d rather build products than manage servers.</em></p>
]]></content:encoded></item><item><title>I Stopped Buying SaaS Boilerplates. Here's What I Buy Instead.</title><link>https://lakshminp.com/2026/01/saas-boilerplates-alternative/</link><pubDate>Thu, 08 Jan 2026 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2026/01/saas-boilerplates-alternative/</guid><category>essays</category><category>saas</category><description>I used to collect SaaS boilerplates like some people collect vintage wine.
ShipFast. LaunchFast. ShipQuick. QuickShip. FastLaunch. LaunchQuick. (I may be making some of these up. I genuinely can’t tell anymore.)
Each one promised the same thing: “Save 40 hours of setup! Auth, payments, email — all pre-configured!”
And they delivered. Sort of. You got a codebase with 47 features, of which you needed 3. You spent 20 hours understanding their architectural decisions. Then another 20 hours ripping out the features you didn’t need. Then another 10 hours wondering why they chose that ORM.</description><content:encoded><![CDATA[<p>I used to collect SaaS boilerplates like some people collect vintage wine.</p>
<p>ShipFast. LaunchFast. ShipQuick. QuickShip. FastLaunch. LaunchQuick. (I may be making some of these up. I genuinely can’t tell anymore.)</p>
<p>Each one promised the same thing: “Save 40 hours of setup! Auth, payments, email — all pre-configured!”</p>
<p>And they delivered. Sort of. You got a codebase with 47 features, of which you needed 3. You spent 20 hours understanding their architectural decisions. Then another 20 hours ripping out the features you didn’t need. Then another 10 hours wondering why they chose <em>that</em> ORM.</p>
<p>Revolutionary time savings.</p>
<h1 id="what-boilerplates-actually-sold-you"><strong>What Boilerplates Actually Sold You</strong></h1>
<p>Let’s be honest about what you were paying for:</p>
<ol>
<li>
<p><strong>Code you didn’t want to write</strong> — Auth flows, Stripe webhooks, email templates</p>
</li>
<li>
<p><strong>Decisions you didn’t want to make</strong> — Folder structure, state management, API patterns</p>
</li>
<li>
<p><strong>Security patterns you didn’t know</strong> — CSRF tokens, rate limiting, input sanitization</p>
</li>
</ol>
<p>The first two? Claude Code handles those in minutes now.</p>
<p>The third one? That’s where it gets interesting.</p>
<h1 id="the-security-argument-and-why-its-half-right"><strong>The Security Argument (And Why It’s Half Right)</strong></h1>
<p>I’ve seen this take on Reddit: “AI is careless with security and exposes secret keys.”</p>
<p>Fair. I’ve watched Claude Code cheerfully commit <code>.env</code> files to git(not now, in its early days). I’ve seen it generate SQL queries that would make Bobby Tables proud.</p>
<p>But here’s the thing: I’ve also seen <em>paid boilerplates</em> ship with hardcoded API keys in example files. I’ve seen “battle-tested” starter kits with XSS vulnerabilities that a first-year CS student would catch.</p>
<p>The boilerplate isn’t magic. It’s just someone else’s code. Sometimes that someone else knew what they were doing. Sometimes they were just faster at shipping than you.</p>
<h1 id="what-claude-code-actually-changes"><strong>What Claude Code Actually Changes</strong></h1>
<p>Ask Claude Code to set up Stripe webhooks.</p>
<p>Watch it scaffold the endpoint, handle signature verification, implement idempotency, and add proper error handling. In about 3 minutes.</p>
<p>Then ask it why it made each decision.</p>
<p>That’s the part boilerplate sellers don’t want you to think about. The boilerplate gives you code. Claude Code gives you code <em>and</em> explains the reasoning. You walk away actually understanding webhook signature verification instead of just copy-pasting it.</p>
<h1 id="the-real-question"><strong>The Real Question</strong></h1>
<p>Do you know what to ask for?</p>
<p>If you understand auth flows, webhook handling, rate limiting, and input sanitization — Claude Code replaces the boilerplate entirely. You’re paying $299 for code you can now generate in a conversation.</p>
<p>If you don’t know what you don’t know — the boilerplate is documentation-as-code. It shows you “here’s how someone who’s shipped 50 SaaS apps structures their webhook handlers.”</p>
<p>But here’s the thing: Claude Code <em>also</em> knows how someone who’s shipped 50 SaaS apps structures their webhook handlers. You just have to ask.</p>
<h1 id="the-uncomfortable-middle-ground"><strong>The Uncomfortable Middle Ground</strong></h1>
<p>Some boilerplates still earn their keep:</p>
<ul>
<li>
<p><strong>Active communities</strong> that find and patch subtle bugs</p>
</li>
<li>
<p><strong>Security audits</strong> by actual security people (rare, but they exist)</p>
</li>
<li>
<p><strong>Opinionated architecture</strong> from someone who’s felt the pain of bad decisions</p>
</li>
</ul>
<p>But most boilerplates? They’re charging you for the labor of stitching together open-source packages. That labor is now approximately free.</p>
<h1 id="the-pragmatic-take"><strong>The Pragmatic Take</strong></h1>
<p>Use Claude Code to build your first few projects from scratch.</p>
<p>You’ll learn the patterns. You’ll understand <em>why</em> you need idempotency keys on webhook handlers. You’ll feel the pain of forgetting CSRF protection and then never forget it again.</p>
<p>Then you’ll realize you never needed the $299 boilerplate.</p>
<p>You needed the knowledge it contained.</p>
<p>That knowledge is now a conversation away.</p>
<p><em>The $299 boilerplate sold you fish. Claude Code teaches you to fish while also catching the fish for you. Your mileage may vary, batteries not included, void where prohibited.</em></p>
]]></content:encoded></item><item><title>I Found a Business Idea and Shipped It in One Claude Code Session</title><link>https://lakshminp.com/2026/01/claude-code-ship-one-session/</link><pubDate>Tue, 06 Jan 2026 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2026/01/claude-code-ship-one-session/</guid><category>essays</category><category>claude-code</category><category>saas</category><description>I shipped a new product landing page yesterday. Not “finished the design.” Not “pushed to staging.” Live. Accepting waitlist signups. DNS propagated. The whole thing.
Time from “huh, interesting Reddit post” to “supabyoi.com is live”: under an hour.
This is either impressive or terrifying, depending on how you feel about the pace of software development in 2026.
The Setup I’ve been building a Reddit research tool that lives inside Claude Code. It monitors subreddits, scores posts against your interests, and helps you find signals in the noise. The tool uses Reddit’s public JSON endpoints—no API keys required, because Reddit doesn’t issue them anymore.</description><content:encoded><![CDATA[<p>I shipped a new product landing page yesterday. Not “finished the design.” Not “pushed to staging.” Live. Accepting waitlist signups. DNS propagated. The whole thing.</p>
<p>Time from “huh, interesting Reddit post” to “<a href="http://supabyoi.com/" rel="external nofollow noopener" class="lnp-link">supabyoi.com</a> is live”: under an hour.</p>
<p>This is either impressive or terrifying, depending on how you feel about the pace of software development in 2026.</p>
<h1 id="the-setup"><strong>The Setup</strong></h1>
<p>I’ve been building a Reddit research tool that lives inside Claude Code. It monitors subreddits, scores posts against your interests, and helps you find signals in the noise. The tool uses Reddit’s public JSON endpoints—no API keys required, because Reddit doesn’t issue them anymore.</p>
<p>That’s not hyperbole. Reddit recently announced they’re “ending self-service API access.” You can’t just create an app and get keys anymore. You have to submit a request form, explain your use case, and wait for approval. The approval that, according to r/redditdev, never comes. “Tickets rejected, modmail ignored, admin DM ignored.” One developer summed it up: “I don’t believe anyone is getting API access for small personal use at this point.”</p>
<p>They’re pushing everyone to Devvit, their walled-garden platform. JavaScript only. Runs on their servers. Limited to what they allow.</p>
<p>If you want Reddit data for your own tools, you either pay enterprise rates, beg for approval, or use public endpoints like a normal browser would. I chose option three.</p>
<p>GummySearch learned this the hard way. They built a Reddit research tool, hit $11k/month MRR, served 135,000 users. Then Reddit wouldn’t give them a commercial license. They’re <a href="https://gummysearch.com/final-chapter/" rel="external nofollow noopener" class="lnp-link">shutting down by December 2026</a>. The founder didn’t want to operate “looking over your shoulder every day.”</p>
<p>Public endpoints don’t have that problem. Same data. No license to revoke.</p>
<p>I had the tool pointed at r/Supabase, watching for pain points. Standard demand validation stuff.</p>
<p>It surfaced a pattern across multiple threads. <a href="https://www.reddit.com/r/Supabase/comments/1joufox/im_a_massproject_starter_supabase_aint_for_me/" rel="external nofollow noopener" class="lnp-link">“I’m a mass-project starter. Supabase ain’t for me?”</a> (41 upvotes, 27 comments). <a href="https://www.reddit.com/r/Supabase/comments/1i3mduv/is_selfhosting_supabase_worth_it/" rel="external nofollow noopener" class="lnp-link">“Is Self-Hosting Supabase Worth It?”</a> (73 upvotes, 60 comments).</p>
<p>The pain: Supabase’s free tier caps you at 2 projects. Pro tier is $25/month plus $10 per additional project. If you’re an indie dev shipping lots of small bets, you burn through that limit fast.</p>
<p>Supabase is genuinely great for rapid prototyping—I use it myself. The pricing just doesn’t fit the small bets workflow.</p>
<p>The comments were gold:</p>
<blockquote>
<p>“It feels like a bait-and-switch where the upgrade appears to remove project limits, only to hit you with unexpected per-project fees”</p>
<p>“Setting it up properly takes time, maintaining it takes time, keeping the server secure takes time”</p>
</blockquote>
<blockquote>
<p>“The setup process is extensive, unclear and often frustrating”</p>
<p>“Very strange pricing model, which is kind of unacceptable”</p>
</blockquote>
<p><strong>Translation:</strong> Indie devs love Supabase for building fast. They hate the pricing when they ship a lot. They want to self-host but are terrified of maintaining it.</p>
<h1 id="the-evaluation"><strong>The Evaluation</strong></h1>
<p>I have a framework for this. Open source project + operational complexity + permissive license = potential hosting business. I’ve been running variations of this for a while.</p>
<p>I asked Claude—right there in the same session—to run the threads through the framework:</p>
<p><strong>Pain point</strong>: Real. Multi-project pricing punishes prolific shippers.<br>
<strong>License</strong>: Apache 2.0. Clear.<br>
<strong>Operational complexity</strong>: High. Supabase runs ~12 services.<br>
<strong>Existing managed option</strong>: Yes, but that’s the pain source—not the solution.</p>
<p>Then the key insight: I’m not competing with Supabase Cloud on hosting. I’m offering care and feeding for self-hosted instances. Different model entirely.</p>
<ul>
<li>
<p>They bring their own VPS (Hetzner, $10-15/month)</p>
</li>
<li>
<p>I handle upgrades, backups, security</p>
</li>
<li>
<p>Fixed monthly fee: $25. Unlimited instances.</p>
</li>
</ul>
<p>One customer with 5 projects: $25 from me + $15 VPS = $40 total vs $75 on Supabase Cloud.</p>
<h1 id="the-build"><strong>The Build</strong></h1>
<p>Here’s where it gets fast.</p>
<p>I told Claude:</p>
<p>“Create a landing page. Tailwind, not CDN. Minimal. Dev-focused. Static HTML.”</p>
<p>Claude scaffolded the project structure, wrote the copy, set up the build pipeline. I tweaked the value prop and added my ConvertKit form.</p>
<p>Then:</p>
<p>“Push to GitHub, I’ll deploy to Cloudflare Pages.”</p>
<p>Done.</p>
<p>Total time building the landing page: maybe 20 minutes. Most of that was me fiddling with colors.</p>
<h1 id="the-stack"><strong>The Stack</strong></h1>
<p>For the curious:</p>
<p><strong>Landing page</strong>: Static HTML, Tailwind CSS, Cloudflare Pages<br>
<strong>Waitlist</strong>: ConvertKit embed<br>
<strong>Domain</strong>: Namecheap (purchase) → Cloudflare (DNS)<br>
<strong>Total cost so far</strong>: $12 for the domain</p>
<p>The actual product will be FastAPI + Supabase (yes, the irony) + HTMX. SSH into customer VMs. Cron jobs for backups. Simple. I can ship a working beta this week.</p>
<h1 id="the-point"><strong>The Point</strong></h1>
<p>This isn’t about Supabyoi specifically. It’s about the workflow.</p>
<p><strong>Old way</strong>:</p>
<ol>
<li>
<p>Have idea</p>
</li>
<li>
<p>Think about it for weeks</p>
</li>
<li>
<p>Research competitors</p>
</li>
<li>
<p>Write PRD</p>
</li>
<li>
<p>Design mockups</p>
</li>
<li>
<p>Build MVP</p>
</li>
<li>
<p>Realize nobody wants it</p>
</li>
<li>
<p>Total time: 3 months</p>
</li>
</ol>
<p><strong>New way</strong>:</p>
<ol>
<li>
<p>Tool surfaces interesting signal</p>
</li>
<li>
<p>Ask Claude to validate against framework</p>
</li>
<li>
<p>Ask Claude to build landing page</p>
</li>
<li>
<p>Ship</p>
</li>
<li>
<p>See if anyone signs up</p>
</li>
<li>
<p>Total time: 1 hour</p>
</li>
</ol>
<p>The landing page is a hypothesis test. Not a commitment. If I get 50 waitlist signups, I build the thing. If I get 5, I move on. The cost of being wrong is $12 and an hour of my time.</p>
<h1 id="about-that-reddit-tool"><strong>About That Reddit Tool</strong></h1>
<p>I’ve been quietly building this for months. It’s how I found the signal that led to this post.</p>
<p>The key: it lives inside Claude Code. Not a separate app. Not a browser tab. Right there in my terminal, in the same session where I’m writing code and shipping products.</p>
<p>The architecture: Crawler runs locally or on your VPS (Reddit can’t shut you down if they can’t block your IP). Data syncs to a backend. You query it with natural language through Claude. “What are people complaining about in r/Supabase?” → ranked list of pain points with source threads. Then in the same breath: “Evaluate this against my validation framework.” Then: “Build me a landing page.”</p>
<p>One session. Research to shipping.</p>
<p>No Reddit API keys because Reddit killed self-service access. Uses public endpoints. Same data you’d see browsing the site. Your IP, your rate limits, no approval form that never gets answered.</p>
<p>I’m not ready to launch it yet, but if you want early access, DM me on <a href="https://linkedin.com/in/lakshminp" rel="external nofollow noopener" class="lnp-link">LinkedIn</a> or <a href="https://x.com/lakshminp" rel="external nofollow noopener" class="lnp-link">Twitter/X</a>.</p>
<h1 id="the-takeaway"><strong>The Takeaway</strong></h1>
<p>The leverage is real. One person, one AI assistant, one hour, one live product.</p>
<p>The bottleneck isn’t building anymore. It’s finding the right thing to build. That’s why the Reddit tool matters more than the Supabase thing. The tool finds signals. Claude validates them. Claude builds the test. You watch the data.</p>
<p>Small bets at scale.</p>
<p><a href="https://supabyoi.com/" rel="external nofollow noopener" class="lnp-link">supabyoi.com</a> is live. Let’s see what happens.</p>
<p><code>&lt;fingers-crossed/&gt;</code></p>
]]></content:encoded></item><item><title>The Indie Dev Edge in the Age of AI</title><link>https://lakshminp.com/2025/10/indie-dev-ai-advantage/</link><pubDate>Mon, 27 Oct 2025 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2025/10/indie-dev-ai-advantage/</guid><category>essays</category><category>saas</category><description>Everyone and their dog’s obsessed with writing code faster.
AI makes us 10x writers. 100x typists. Whatever.
But nobody’s talking about becoming a 10x reader.
And here’s the kicker — AI is vomiting out more code than ever. Which means you need to read and understand more code than ever. The bottleneck isn’t writing anymore. It’s comprehension, judgment, and knowing when to hit delete instead of commit.
Why this Matters More Now The AI paradox Claude can churn out 500 lines of backend logic in 30 seconds. But you still have to:</description><content:encoded><![CDATA[<p>Everyone and their dog’s obsessed with writing code faster.</p>
<p>AI makes us 10x writers. 100x typists. Whatever.</p>
<p>But nobody’s talking about becoming a 10x <em>reader</em>.</p>
<p>And here’s the kicker — AI is vomiting out more code than ever. Which means <em>you</em> need to read and understand more code than ever. The bottleneck isn’t writing anymore. It’s comprehension, judgment, and knowing when to hit delete instead of commit.</p>
<h1 id="why-this-matters-more-now"><strong>Why this Matters More Now</strong></h1>
<h2 id="the-ai-paradox"><strong>The AI paradox</strong></h2>
<p>Claude can churn out 500 lines of backend logic in 30 seconds. But <em>you</em> still have to:</p>
<ul>
<li>
<p>Check if it actually does what you asked</p>
</li>
<li>
<p>Notice the subtle bug hiding in error handling</p>
</li>
<li>
<p>Decide whether that abstraction will come back to bite you</p>
</li>
<li>
<p>Understand it well enough to fix it when the PM changes the requirements tomorrow</p>
</li>
</ul>
<p>AI can write all the code in the world. It still can’t tell you if it’s <em>good</em>.</p>
<h2 id="the-reality"><strong>The reality</strong></h2>
<p>Juniors with AI now ship code at senior speed. The problem? They can’t tell good generated code from hot garbage. They move fast, break things… and then ask you to review it.</p>
<h2 id="the-unlock"><strong>The unlock</strong></h2>
<p>Seniors with reading chops use AI without becoming its pet. They skim generated code like Neo reading the Matrix — “yeah, that’s an off-by-one bug right there.” Reading is the gate. Writing is just the noise.</p>
<h1 id="the-code-reading-muscle"><strong>The Code Reading Muscle</strong></h1>
<p>It’s not “reading comprehension.” It’s mental pattern recognition with caffeine.</p>
<p><strong>Pattern recognition</strong> — You see <code>if err != nil { return nil, err }</code> and your brain whispers, “Go boilerplate, nothing to see here.”</p>
<p><strong>Architecture intuition</strong> — You open a repo and know where the dead bodies are buried just from the folder structure.</p>
<p><strong>Bug radar</strong> — That spidey-sense that tingles before you even scroll — something’s off. Usually missing validation, or someone “cleverly” sharing a global.</p>
<p><strong>Context switching speed</strong> — You can hop from React component → API → database query → back again without losing the plot.</p>
<p><strong>Abstraction unpacking</strong> — You see <code>userService.authenticate()</code> and immediately imagine the 12 files hiding behind that call.</p>
<p>That’s the muscle. Reading is pattern spotting at light speed.</p>
<h1 id="exercises-that-actually-work"><strong>Exercises That Actually Work</strong></h1>
<h2 id="1-the-5-minute-codebase-scan"><strong>1. The 5-Minute Codebase Scan</strong></h2>
<p>Pick a random GitHub repo. Small, readable.</p>
<p>Set a 5-minute timer. Try to answer:</p>
<ul>
<li>
<p>What does it do?</p>
</li>
<li>
<p>What’s the core abstraction?</p>
</li>
<li>
<p>Where would you add a new feature?</p>
</li>
<li>
<p>What’s the sketchiest piece of code?</p>
</li>
</ul>
<p>You’ll probably be wrong the first few times. Perfect. You’re training intuition, not memorizing trivia.</p>
<p>Start with stacks you know. Then branch out. Eventually, try reading something alien — that’s where growth hides.</p>
<h2 id="2-ai-code-review-roulette"><strong>2. AI Code Review Roulette</strong></h2>
<p>Ask Claude or ChatGPT to write something — a rate limiter, a REST API, a React hook.</p>
<p>Now, <em>don’t run it</em>.</p>
<p>Read it like a detective:</p>
<ul>
<li>
<p>What could break?</p>
</li>
<li>
<p>What smells?</p>
</li>
<li>
<p>What would you refactor?</p>
</li>
</ul>
<p>Then run it and see how wrong (or right) you were.</p>
<p>Do this enough and you’ll develop a sixth sense for AI bugs — the kind that crash in production at 3 a.m.</p>
<p>Bonus: Ask two AIs the same thing. Which one’s code would you rather maintain? Why? That’s your taste muscle forming.</p>
<h2 id="3-the-changelog-detective"><strong>3. The Changelog Detective</strong></h2>
<p>Pick a library you use every day. Go to its GitHub releases. Read the commit diffs for a minor or patch bump.</p>
<p>Ask:</p>
<ul>
<li>
<p>Why was this changed?</p>
</li>
<li>
<p>What broke?</p>
</li>
<li>
<p>What tradeoff did the maintainer choose?</p>
</li>
</ul>
<p>You’ll start seeing the real engineering behind the facade. That’s where mastery lives.</p>
<h2 id="4-explain-it-to-a-duck"><strong>4. Explain It to a Duck</strong></h2>
<p>Grab a gnarly function.</p>
<p>Now, explain it in plain English. No jargon.</p>
<p>If you can’t? You don’t actually understand it. Keep at it.</p>
<p>Bad: “It maps and filters the array.”</p>
<p>Good: “It finds active users in the last 30 days, sorted by login time.”</p>
<p>That’s real understanding. Not just parroting syntax.</p>
<h2 id="5-the-no-running-challenge"><strong>5. The “No Running” Challenge</strong></h2>
<p>Write a small program. 50–100 lines. Don’t run it.</p>
<p>Read it twice and predict:</p>
<ul>
<li>
<p>What will the output be?</p>
</li>
<li>
<p>Where will it break?</p>
</li>
<li>
<p>What edge case will it choke on?</p>
</li>
</ul>
<p>Then run it. Reality check time.</p>
<p>This builds your internal compiler — the one that helps you debug production when the system’s on fire and kubectl exec isn’t helping.</p>
<h1 id="how-this-compounds-over-time"><strong>How This Compounds Over Time</strong></h1>
<p><strong>0–2 years:</strong></p>
<p>You read slow. You write slow. You Google “Python for loop syntax” a lot.</p>
<p><strong>AI enters:</strong></p>
<p>Suddenly you write <em>fast</em>. But you still read like a confused tourist. You ship more bugs, faster.</p>
<p><strong>2–5 years:</strong></p>
<p>Now you read fast <em>and</em> write fast. You glance at AI output and see through it.</p>
<p><strong>5+ years:</strong></p>
<p>You can parachute into any repo and get the lay of the land in minutes. You’re debugging across services. Reading is 80% of your job. Writing is an afterthought.</p>
<p>Every project you touch sharpens the radar. Every bug you fix improves your mental models. Every codebase you inherit becomes easier to digest. That’s compounding.</p>
<p>Also: boring stacks help.</p>
<p>You read the same patterns — Postgres, Redis, Express — again and again until it’s second nature. No cognitive tax. Fancy tech makes you start from zero every time.</p>
<h1 id="daily-practice-aka-the-boring-way-that-works"><strong>Daily Practice (a.k.a. the Boring Way That Works)</strong></h1>
<ul>
<li>
<p><strong>Morning ritual:</strong> Read one function before writing a line. Two minutes. That’s it.</p>
</li>
<li>
<p><strong>PR reviews:</strong> Don’t just skim — ask <em>why</em> the author made those choices.</p>
</li>
<li>
<p><strong>AI pair programming:</strong> Never accept AI code blindly. Read before you run. Especially when you’re in a rush.</p>
</li>
<li>
<p><strong>Weekend deep dives:</strong> Pick one OSS project a month and read the core 200 lines.</p>
</li>
<li>
<p><strong>Bug postmortems:</strong> After fixing something, read the surrounding code. Figure out <em>why</em> it broke in the first place.</p>
</li>
</ul>
<p>That’s how you actually build the muscle. Quietly. Daily.</p>
<h1 id="dont-fake-it"><strong>Don’t Fake It</strong></h1>
<p>Speed reading code to “feel productive” is fake progress.</p>
<p>If you can’t explain it, you don’t understand it.</p>
<p>Red flags:</p>
<ul>
<li>
<p>Approving PRs faster than Slack loads</p>
</li>
<li>
<p>Forgetting what your own code does after a week</p>
</li>
<li>
<p>Acting surprised when it breaks exactly how it looks like it would</p>
</li>
</ul>
<p>Slow down. Read with intent. Comprehension beats velocity every single time.</p>
<h1 id="the-meta-skill"><strong>The Meta-Skill</strong></h1>
<p>AI will keep getting better at writing code. It’ll never understand <em>why</em> the code matters.</p>
<p>That’s your job.</p>
<p>The developer who can <em>read</em> code — fast, deeply, intuitively — will always win.</p>
<p>Start building the muscle. It ages like wine.</p>
<h2 id="do-this-today"><strong>Do this today:</strong></h2>
<p>Pick one exercise. Do it now. Time yourself. Do it again next week. You’ll notice you’re faster — not at typing, but at <em>thinking</em>.</p>
<p>That’s the real 10x skill nobody’s bragging about on LinkedIn.</p>
]]></content:encoded></item><item><title>What every indie dev should master before asking AI to build for them</title><link>https://lakshminp.com/2025/10/ai-coding-prerequisites/</link><pubDate>Sun, 19 Oct 2025 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2025/10/ai-coding-prerequisites/</guid><category>essays</category><category>saas</category><description>Before AI coding assistants, I wasted months chasing the “right stack.”
React or Vue? Flask or Django? Docker or bare VPS?
I’d open fifty tabs and still end up staring at a blinking cursor.
Now, we’re in a world where you can describe your idea and watch an AI spin up a working prototype. It feels magical — until you try to debug it.
The truth is, vibe coding only works if you understand what the AI is building for you.</description><content:encoded><![CDATA[<p>Before AI coding assistants, I wasted months chasing the “right stack.”</p>
<p>React or Vue? Flask or Django? Docker or bare VPS?</p>
<p>I’d open fifty tabs and still end up staring at a blinking cursor.</p>
<p>Now, we’re in a world where you can <em>describe</em> your idea and watch an AI spin up a working prototype. It feels magical — until you try to debug it.</p>
<p>The truth is, vibe coding only works if you understand what the AI is building for you.</p>
<p>Otherwise, you’re just rearranging generated code and hoping for the best.</p>
<p>So, before you ask AI to build your SaaS, here’s what you need to master first.</p>
<p>These aren’t frameworks or libraries — they’re the mental models that make AI your assistant, not your babysitter.</p>
<h2 id="version-control-command-the-timeline"><strong>Version Control: Command the Timeline</strong></h2>
<p>I used to treat Git like a magical undo button — until it undid <em>everything.</em></p>
<p>Even as a solo builder, Git is your safety net. Learn to branch, merge, revert, and tag with confidence.</p>
<p>Every “oh no” moment becomes recoverable when you know how to roll back.</p>
<p>🧠 <em>Pro tip:</em></p>
<p>Integrate your favorite AI tool with GitHub’s <strong>MCP</strong>. You can tell it to open PRs, summarize diffs, or write changelogs.</p>
<p>But here’s the catch — to delegate effectively, you need to <em>understand</em> version control first.</p>
<p>Also, <strong><a href="https://marketplace.visualstudio.com/items?itemName=kahole.magit" rel="external nofollow noopener" class="lnp-link">Magit</a></strong> <a href="https://marketplace.visualstudio.com/items?itemName=kahole.magit" rel="external nofollow noopener" class="lnp-link">for VSCode</a> is an underrated gem. It makes Git feel almost fun.</p>
<h2 id="data-model-dont-just-store"><strong>Data: Model, Don’t Just Store</strong></h2>
<p>No SaaS survives without a solid data model. I learned that the hard way, after my “fast” prototype crawled because I hadn’t indexed anything.</p>
<p>Knowing how to design schemas, choose keys, and plan migrations will save you more pain than any ORM ever could.</p>
<p>Your data model <em>will</em> evolve. Be ready for it.</p>
<p>🧠 <em>AI Tip:</em></p>
<p>Discuss your schema with your LLM.</p>
<p>Ask, <em>“What should I index?”</em>, <em>“How will this evolve?”</em>, or <em>“What’s the best way to handle this relationship?”</em></p>
<p>You’ll get insights that feel like having a senior engineer on call.</p>
<h2 id="http--apis-speak-the-native-language"><strong>HTTP &amp; APIs: Speak the Native Language</strong></h2>
<p>Every SaaS runs on HTTP.</p>
<p>Learn verbs, status codes, and what to return when things go wrong.</p>
<p>In my early days, I’d return 200 for everything — even errors.</p>
<p>Don’t do that. It makes your users (and future self) miserable.</p>
<p>🧠 <em>AI Tip:</em></p>
<p>Tools like <strong><a href="https://context7.com/" rel="external nofollow noopener" class="lnp-link">Context7</a></strong> make working with APIs much easier.</p>
<p>And yes, keep an <strong>OpenAPI spec</strong>. It’s documentation for your future self, not just a team.</p>
<p>(And between us — your first SaaS might not even <em>need</em> an API. We’ll talk about that soon.)</p>
<h2 id="authentication-shop-the-shelf"><strong>Authentication: Shop the Shelf</strong></h2>
<p>I built my own login systems multiple times.</p>
<p>It always ended with regret and sleepless nights.</p>
<p>Don’t code your own auth unless you’re writing a security product.</p>
<p>Use your framework’s built-in module, or plug in Supabase, Clerk, or Auth0. I wrote about this:</p>
<p>Security is not where you show creativity.</p>
<p>🧠 <em>AI Tip:</em></p>
<p>LLMs can wire up cookie handling, password resets, and JWTs, but make sure <em>you</em> know where your secrets live and how they expire.</p>
<h2 id="frontend-literacy-communicate-dont-overcomplicate"><strong>Frontend Literacy: Communicate, Don’t Overcomplicate</strong></h2>
<p>Frontend used to terrify me. CSS felt like chaos, and every “simple” change broke something else.</p>
<p>Then I discovered the power of simple stacks — HTML, Tailwind, and maybe HTMX or Alpine.js.</p>
<p>You don’t need React to make a clean, usable product.</p>
<p>You just need enough literacy to connect your API to a button and make it look decent.</p>
<p>🧠 <em>AI Tip:</em></p>
<p>AI is terrible at design. It’ll give you perfect code for ugly UIs.</p>
<p>Feed it visual specs instead of vague prompts.</p>
<p>And if you can, learn a bit of design — not to be a designer, but to avoid obvious aesthetic crimes.</p>
<h2 id="caching-respect-the-users-time"><strong>Caching: Respect the User’s Time</strong></h2>
<p>I once doubled my server bill because I didn’t cache anything.</p>
<p>Caching isn’t optimization — it’s respect.</p>
<p>You don’t need to master Redis or CDN tuning, but understand the concept:</p>
<p>store what doesn’t change, reuse what you can.</p>
<p>🧠 <em>AI Tip:</em></p>
<p>Ask, “Where can I add caching for quick wins?”</p>
<p>AI can spot bottlenecks faster than you think.</p>
<h2 id="containers--deployment-build-once-run-anywhere"><strong>Containers &amp; Deployment: Build Once, Run Anywhere</strong></h2>
<p>I used to fear Docker. It felt like wizardry.</p>
<p>Then I realized it’s just consistency — the same environment, everywhere.</p>
<p>Learn how to write a Dockerfile and deploy with Docker Compose or Fly.io.</p>
<p>That’s 90% of what you’ll ever need early on.</p>
<p>Kubernetes can wait — though it’s worth knowing <em>why</em> it exists.</p>
<p>🧠 <em>AI Tip:</em></p>
<p>Let the AI write your Dockerfile, but read every line.</p>
<p>A single bad layer can bloat your image from 100MB to 1GB.</p>
<h2 id="system-design-dont-overbuild--yet"><strong>System Design: Don’t Overbuild — Yet</strong></h2>
<p>When I first started learning about queues, event buses, and load balancers, I felt like I’d unlocked a hidden level of engineering.</p>
<p>I wanted to use <em>everything</em>.</p>
<p>So I did — and my “simple” SaaS turned into a distributed Rube Goldberg machine.</p>
<p>My future self hated me for it.</p>
<p>Here’s the quiet truth about system design:</p>
<p>the more you know, the more dangerous you become.</p>
<p>Because knowledge tempts you to overengineer.</p>
<p>To solve problems you don’t have yet.</p>
<p>To optimize for scale that may never come.</p>
<p>But good design isn’t about sophistication — it’s about restraint.</p>
<p>It’s choosing clarity today over hypothetical performance tomorrow.</p>
<p>🧠 <em>AI Tip:</em></p>
<p>Ask your coding assistant to sketch a <em>simpler</em> version of what you have in mind.</p>
<p>Say, “Can this work without queues?” or “Can we handle this in-process first?”</p>
<p>Sometimes the best architecture is the one that fits in your head.</p>
<h2 id="observability-see-before-you-panic"><strong>Observability: See Before You Panic</strong></h2>
<p>The most painful bugs are the invisible ones.</p>
<p>You can’t fix what you can’t see.</p>
<p>Start simple: print logs, expose /healthz, and add uptime checks.</p>
<p>You don’t need fancy dashboards — just awareness.</p>
<p>🧠 <em>AI Tip:</em></p>
<p>Ask your LLM to set up Sentry, logging middlewares, or structured logs.</p>
<p>AI is great at the boring setup — you handle the insights.</p>
<h2 id="shell--scripting-glue-everything-together"><strong>Shell &amp; Scripting: Glue Everything Together</strong></h2>
<p>Bash saved me more times than I can count.</p>
<p>A simple script to restart a service, clean a directory, or back up a DB — these are invisible superpowers.</p>
<p>Learn your way around permissions, env vars, grep, and tmux.</p>
<p>This is what separates the “can’t deploy” dev from the “fixed it in 5 minutes” builder.</p>
<p>🧠 <em>AI Tip:</em></p>
<p>Have AI generate shell scripts — but <strong>never</strong> run them blindly.</p>
<p>Understand before you execute.</p>
<h2 id="security-the-habit-not-the-skill"><strong>Security: The Habit, Not the Skill</strong></h2>
<p>You might’ve noticed I didn’t give security its own section. That’s intentional.</p>
<p>It’s not a tool — it’s a habit.</p>
<p>Every time you touch authentication, data, or deployment, think:</p>
<blockquote>
<p>“If this were compromised, what breaks?”</p>
</blockquote>
<p>Use HTTPS. Hash passwords. Never hardcode secrets.</p>
<p>Most breaches come from negligence, not genius-level hacking. Something I like to call the <strong>ignorance debt</strong>.</p>
<h2 id="frameworks-languages-and-everything-else"><strong>Frameworks, Languages, and Everything Else</strong></h2>
<p>By now, someone will say, “But what about React? Django? Go? Rust? CI/CD?”</p>
<p>All valid. All secondary.</p>
<p>Frameworks are shortcuts, not foundations.</p>
<p>Languages are dialects — once you understand these fundamentals, syntax becomes trivia.</p>
<p>Testing, CI, and cloud scaling make sense only <em>after</em> you’ve shipped something worth scaling.</p>
<p>Learn these ten areas deeply, and AI suddenly becomes 10x more effective.</p>
<p>Because now, you know what to ask, what to skip, and when to stop it from hallucinating an entire microservice.</p>
<h2 id="the-indie-dev-reality"><strong>The Indie Dev Reality</strong></h2>
<p>Vibe coding isn’t about skipping the hard parts — it’s about <em>sequencing</em> them right.</p>
<p>AI gives you speed, but not direction.</p>
<p>These fundamentals are your compass.</p>
<p>Learn them once, and you’ll never fear new tools again.</p>
<p>Everything else — frameworks, language wars, fancy hosting — becomes optional flavor.</p>
<p>Because in the end, you don’t need to know everything.</p>
<p>You just need to know <em>enough</em> to ship, fix, and try again.</p>
]]></content:encoded></item><item><title>Your SaaS Will Break — Here’s How to See It Coming</title><link>https://lakshminp.com/2025/10/saas-monitoring-basics/</link><pubDate>Sat, 18 Oct 2025 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2025/10/saas-monitoring-basics/</guid><category>essays</category><category>saas</category><description>You know that peaceful moment when you’ve just deployed your SaaS MVP?
No users yet. No traffic. Everything looks fine.
It’s the most deceptive calm in tech.
Because here’s what happens next:
Someone signs up. A few cron jobs kick in. A background task fails silently.
And you have no clue why.
Not because you’re a bad engineer.
But because you never gave yourself eyes.
I’ve been there — staring at a blank terminal, trying to reproduce a bug I can’t see, because I didn’t bother adding even basic observability before launch.</description><content:encoded><![CDATA[<p>You know that peaceful moment when you’ve just deployed your SaaS MVP?</p>
<p>No users yet. No traffic. Everything looks <em>fine</em>.</p>
<p>It’s the most deceptive calm in tech.</p>
<p>Because here’s what happens next:</p>
<p>Someone signs up. A few cron jobs kick in. A background task fails silently.</p>
<p>And you have <em>no clue</em> why.</p>
<p>Not because you’re a bad engineer.</p>
<p>But because you never gave yourself eyes.</p>
<p>I’ve been there — staring at a blank terminal, trying to reproduce a bug I can’t see, because I didn’t bother adding even basic observability before launch.</p>
<p>That’s when you realize: you don’t need users to create chaos. You just need time.</p>
<p>Your SaaS <em>will</em> break.</p>
<p>Something small. Something silly. Something preventable.</p>
<p>And when it does, you want breadcrumbs.</p>
<p>You don’t need Grafana dashboards or Prometheus metrics yet.</p>
<p>You just need awareness. A few tiny habits that make you less blind:</p>
<ul>
<li>
<p>Log errors to stdout. Your logs are your first debugger.</p>
</li>
<li>
<p>Add Sentry for unhandled exceptions — because one will always sneak through.</p>
</li>
<li>
<p>Expose a /healthz endpoint. It’s the easiest way to check if your app is even alive.</p>
</li>
<li>
<p>Capture latency in middleware. You don’t need histograms; just print request times.</p>
</li>
</ul>
<p>That’s enough.</p>
<p>You’re not setting up a monitoring stack. You’re giving your future self context.</p>
<p>You’re leaving breadcrumbs for when things go sideways.</p>
<p>Because when that first user says,</p>
<blockquote>
<p>“Hey, your site’s kinda slow today,”</p>
</blockquote>
<p>you’ll know where to look — not just what broke.</p>
<p>I can’t tell you how many times I’ve been grateful for a random log line I wrote months ago.</p>
<p>Future-me has sent past-me several thank-you notes.</p>
<p>So, before you chase new features or users…</p>
<p>Add observability.</p>
<p>Give yourself eyes. 👀</p>
<p>It’s the calmest insurance policy you’ll ever set up.</p>
]]></content:encoded></item><item><title>You’re Making Your SaaS Harder Than It Needs to Be</title><link>https://lakshminp.com/2025/10/saas-simplicity/</link><pubDate>Thu, 16 Oct 2025 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2025/10/saas-simplicity/</guid><category>essays</category><category>saas</category><description>A few weeks ago, I spent an entire evening chasing a bug in a React component that refused to re-render.
I tried useEffect. Then useMemo. Then stared at the dependency array like it had personally wronged me. Eventually, I fixed it — by restarting the dev server.
That’s when it hit me: React wasn’t made for people like me.
React was built for teams — with dedicated frontend engineers, design systems, review processes, and time to care about component hierarchies. I’m just trying to build a SaaS. Alone.</description><content:encoded><![CDATA[<p>A few weeks ago, I spent an entire evening chasing a bug in a React component that refused to re-render.</p>
<p>I tried <code>useEffect</code>. Then <code>useMemo</code>. Then stared at the dependency array like it had personally wronged me. Eventually, I fixed it — by restarting the dev server.</p>
<p>That’s when it hit me: <strong>React wasn’t made for people like me.</strong></p>
<p>React was built for <em>teams</em> — with dedicated frontend engineers, design systems, review processes, and time to care about component hierarchies. I’m just trying to build a SaaS. Alone.</p>
<p>And as a solo dev, every layer of “modern architecture” feels like an extra wall between me and shipping.</p>
<p>I’m not great at React — mediocre, at best. But that’s the point. The tools I use shouldn’t need me to be great at them to get work done.</p>
<p>I don’t hate React. I hate how easily it turns small projects into puzzles.</p>
<p>The setup is never small: package managers, routing, build tools, state management, API layers, hydration. It’s an entire ecosystem just to render some HTML.</p>
<p>At some point, you stop writing features and start maintaining your own framework.</p>
<p>And no — AI coding assistants don’t make this any easier.</p>
<p>They’ll happily generate components, hooks, and entire pages for you. But they also multiply the cognitive load. You end up with auto-written code you didn’t fully read, logic you didn’t author, and bugs you can’t mentally trace.</p>
<p>AI helps you go faster — straight into the same wall.</p>
<p>When the code gets complex, you’re still the one debugging it at 1 a.m., trying to remember why useEffect depends on a variable that no longer exists.</p>
<p>Meanwhile, the old-school Model-View-Controller pattern — the one we abandoned because it wasn’t “modern” enough — still does the job.</p>
<p>Django, Rails, Laravel — these frameworks have one big thing React doesn’t: <strong>a consistent mental model.</strong> You don’t have to remember whether a component is server or client. You just write code that responds to requests and sends back HTML.</p>
<p>MVC assumes you’re one person who wants to move fast. React assumes you’re part of a team that can afford to slow down.</p>
<p>In MVC land, there’s no build step. No hydration mismatch. No npm install that randomly breaks after a week. You can teach a junior developer (or your future self) the whole stack in an afternoon.</p>
<p>The irony is that React is now rediscovering what MVC never forgot. Server components, data fetching, progressive rendering — all old ideas wearing new clothes.</p>
<p>And that’s fine. The web evolves. But if you’re an indie developer building your first or fifth SaaS, you don’t need to play catch-up with every new abstraction.</p>
<p>Complexity is not a sign of progress. It’s often just inertia.</p>
<p>Simplicity compounds. Every decision you <em>don’t</em> make leaves you more energy to focus on what matters — your users, your pricing, your roadmap, your survival.</p>
<p>So if your stack feels heavy, it’s not your idea that’s broken. It’s your setup.</p>
<p>You don’t need a front-end framework to validate your business.</p>
<p>You need feedback. Fast.</p>
<p>And for that, an old-fashioned MVC stack will get you further than a “modern” one built on a mountain of npm packages.</p>
<p>React is powerful — no argument there. But power isn’t the same as momentum.</p>
<p>For indie devs, momentum wins. Every time.</p>
]]></content:encoded></item><item><title>If I Were Starting a New SaaS Today, I'd Do This</title><link>https://lakshminp.com/2025/10/if-i-were-starting-a-saas-today/</link><pubDate>Wed, 15 Oct 2025 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2025/10/if-i-were-starting-a-saas-today/</guid><category>essays</category><category>saas</category><description>Most SaaS projects fail because founders spend weeks building scaffolding instead of features. Here’s how to skip the boilerplate and ship fast.
I’ve built half a dozen SaaS products. Some succeeded. Most failed. But the failures taught me something critical: ideas don’t die from competition—they die from delayed launches.
You lose weeks setting up databases, authentication, APIs, file uploads, and admin panels before writing a single line of actual product code. By the time you’re ready to ship, momentum is gone.</description><content:encoded><![CDATA[<p>Most SaaS projects fail because founders spend weeks building scaffolding instead of features. Here&rsquo;s how to skip the boilerplate and ship fast.</p>
<p>I&rsquo;ve built half a dozen SaaS products. Some succeeded. Most failed. But the failures taught me something critical:
<strong>ideas don&rsquo;t die from competition—they die from delayed launches</strong>.</p>
<p>You lose weeks setting up databases, authentication, APIs, file uploads, and admin panels before writing a single
line of actual product code. By the time you&rsquo;re ready to ship, momentum is gone.</p>
<p>If I were starting today, I&rsquo;d skip all that. I&rsquo;d use Supabase—and I&rsquo;d ship an MVP in days, not months.</p>
<h2 id="the-problem-with-building-from-scratch">The Problem with &ldquo;Building from Scratch&rdquo;</h2>
<p>Building foundations feels productive. You&rsquo;re writing code, making decisions, setting up infrastructure. But you&rsquo;re
not building anything users can touch.</p>
<p>Auth alone consumes days: password hashing, session management, password resets, email verification. Then you need
database migrations, API routes, input validation, error handling. Before you know it, you&rsquo;ve burned two weeks on
scaffolding.</p>
<p><strong>That&rsquo;s two weeks you could&rsquo;ve spent validating whether anyone actually wants what you&rsquo;re building.</strong></p>
<h2 id="why-supabase-changes-everything">Why Supabase Changes Everything</h2>
<p>Supabase isn&rsquo;t just a database. It&rsquo;s a complete backend—authentication, storage, real-time updates, edge functions—packaged
as a single platform. And unlike Firebase, it&rsquo;s built on PostgreSQL, so you&rsquo;re not locked into proprietary tech.</p>
<h3 id="postgresql-foundation">PostgreSQL Foundation</h3>
<p>Every table you create automatically gets REST and GraphQL APIs. No backend needed. Query directly from your frontend
with row-level security enforcing permissions at the database layer.</p>
<div class="lnp-codeblock">
  <div class="lnp-codeblock-head">
    <span>javascript</span>
    <button type="button" class="lnp-codeblock-copy" data-copy aria-label="Copy code">Copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// Fetch user&#39;s tasks directly from the frontend
</span></span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">error</span> <span class="p">}</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">supabase</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">from</span><span class="p">(</span><span class="s1">&#39;tasks&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="s1">&#39;*&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">eq</span><span class="p">(</span><span class="s1">&#39;user_id&#39;</span><span class="p">,</span> <span class="nx">userId</span><span class="p">);</span></span></span></code></pre></div>
</div>
<p>You still get full PostgreSQL power: triggers, extensions, stored procedures, joins, indexes. It&rsquo;s not a toy database—it&rsquo;s
enterprise-grade Postgres with a developer experience that doesn&rsquo;t suck.</p>
<h3 id="authentication-that-just-works">Authentication That Just Works</h3>
<p>Built-in support for email/password, magic links, OTPs, OAuth (Google, GitHub, etc.), and custom SSO. User records live
in your Postgres schema. Add custom fields. Create relationships. No vendor lock-in.</p>
<div class="lnp-codeblock">
  <div class="lnp-codeblock-head">
    <span>javascript</span>
    <button type="button" class="lnp-codeblock-copy" data-copy aria-label="Copy code">Copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// Sign up with email/password
</span></span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">user</span><span class="p">,</span> <span class="nx">error</span> <span class="p">}</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">supabase</span><span class="p">.</span><span class="nx">auth</span><span class="p">.</span><span class="nx">signUp</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">email</span><span class="o">:</span> <span class="s1">&#39;user@example.com&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nx">password</span><span class="o">:</span> <span class="s1">&#39;secure-password&#39;</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Magic link (passwordless)
</span></span></span><span class="line"><span class="cl"><span class="kr">await</span> <span class="nx">supabase</span><span class="p">.</span><span class="nx">auth</span><span class="p">.</span><span class="nx">signInWithOtp</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="nx">email</span><span class="o">:</span> <span class="s1">&#39;user@example.com&#39;</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span></span></span></code></pre></div>
</div>
<p>No JWT libraries. No session stores. No password reset flows. It&rsquo;s handled. You write product code.</p>
<h3 id="real-time-updates-without-redis">Real-Time Updates Without Redis</h3>
<p>WebSocket-based subscriptions give you instant updates on table changes. No message brokers. No Kafka. No Redis pub/sub.</p>
<div class="lnp-codeblock">
  <div class="lnp-codeblock-head">
    <span>javascript</span>
    <button type="button" class="lnp-codeblock-copy" data-copy aria-label="Copy code">Copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// Subscribe to new messages
</span></span></span><span class="line"><span class="cl"><span class="nx">supabase</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">channel</span><span class="p">(</span><span class="s1">&#39;messages&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;postgres_changes&#39;</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">event</span><span class="o">:</span> <span class="s1">&#39;INSERT&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">schema</span><span class="o">:</span> <span class="s1">&#39;public&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">table</span><span class="o">:</span> <span class="s1">&#39;messages&#39;</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span> <span class="p">(</span><span class="nx">payload</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;New message:&#39;</span><span class="p">,</span> <span class="nx">payload</span><span class="p">.</span><span class="k">new</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">})</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">subscribe</span><span class="p">();</span></span></span></code></pre></div>
</div>
<p>Insert a row in your messages table? All connected clients receive it instantly. Build chat, notifications, live dashboards—without
standing up infrastructure.</p>
<h3 id="row-level-security">Row-Level Security</h3>
<p>Database-level authorization policies replace entire backend authorization layers. One policy line defines who can access what.</p>
<div class="lnp-codeblock">
  <div class="lnp-codeblock-head">
    <span>sql</span>
    <button type="button" class="lnp-codeblock-copy" data-copy aria-label="Copy code">Copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="cl"><span class="c1">-- Users can only see their own tasks
</span></span></span><span class="line"><span class="cl"><span class="k">CREATE</span><span class="w"> </span><span class="n">POLICY</span><span class="w"> </span><span class="s2">&#34;Users see own tasks&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="k">ON</span><span class="w"> </span><span class="n">tasks</span><span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="k">SELECT</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="k">USING</span><span class="w"> </span><span class="p">(</span><span class="n">auth</span><span class="p">.</span><span class="n">uid</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">user_id</span><span class="p">);</span></span></span></code></pre></div>
</div>
<p>Policies compose. Multi-tenant? Add tenant_id checks. Admin override? Add role conditions. Security moves from scattered
backend checks to centralized, auditable rules.</p>
<h3 id="storage--edge-functions">Storage &amp; Edge Functions</h3>
<p>Native file upload handling with access rules compatible with row-level security. TypeScript-based edge functions deploy
in seconds for webhooks, scheduled jobs, or integrations.</p>
<div class="lnp-codeblock">
  <div class="lnp-codeblock-head">
    <span>javascript</span>
    <button type="button" class="lnp-codeblock-copy" data-copy aria-label="Copy code">Copy</button>
  </div>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="c1">// Upload file with automatic access control
</span></span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">data</span><span class="p">,</span> <span class="nx">error</span> <span class="p">}</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">supabase</span><span class="p">.</span><span class="nx">storage</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">from</span><span class="p">(</span><span class="s1">&#39;avatars&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">.</span><span class="nx">upload</span><span class="p">(</span><span class="sb">`</span><span class="si">${</span><span class="nx">userId</span><span class="si">}</span><span class="sb">/avatar.png`</span><span class="p">,</span> <span class="nx">file</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Edge function for webhook processing
</span></span></span><span class="line"><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">serve</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">&#39;https://deno.land/std/http/server.ts&#39;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">serve</span><span class="p">(</span><span class="kr">async</span> <span class="p">(</span><span class="nx">req</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kr">const</span> <span class="nx">payload</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">req</span><span class="p">.</span><span class="nx">json</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// Process webhook
</span></span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="k">new</span> <span class="nx">Response</span><span class="p">(</span><span class="s1">&#39;OK&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">status</span><span class="o">:</span> <span class="mi">200</span> <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span></span></span></code></pre></div>
</div>
<h2 id="the-developer-experience-you-deserve">The Developer Experience You Deserve</h2>
<p>The CLI, dashboard, SQL editor, and APIs feel cohesive. You&rsquo;re not juggling five different tools with five different
authentication methods. Everything integrates.</p>
<p>Need to see your database? Open the dashboard. Want to test a query? Use the SQL editor. Ready to deploy a function?
<code>supabase functions deploy</code>. It just works.</p>
<h2 id="open-source--portability">Open Source &amp; Portability</h2>
<p>Unlike Firebase, Supabase runs self-hosted via Docker Compose. Start on their hosted platform. Move to self-hosted
if you outgrow it. Same codebase. Same developer experience.</p>
<p>You&rsquo;re not locked in. Your data is Postgres. Your auth is Postgres. Your files are S3-compatible storage. If Supabase
disappears tomorrow, you can migrate. Try doing that with Firebase.</p>
<h2 id="ship-fast-own-your-stack-avoid-unnecessary-complexity">Ship Fast, Own Your Stack, Avoid Unnecessary Complexity</h2>
<p>This is the indie developer playbook: start small, ship fast, scale naturally. Supabase embodies that philosophy.</p>
<p>You&rsquo;re not choosing between a custom backend and a proprietary platform. Supabase sits in the middle—powerful enough
for serious applications, simple enough to start with one table and an auth flow.</p>
<p><strong>If I were starting a SaaS today, I&rsquo;d skip the scaffolding. I&rsquo;d use Supabase. And I&rsquo;d ship in days—not weeks.</strong></p>
<p>Because the best way to validate an idea isn&rsquo;t to build perfect infrastructure. It&rsquo;s to put something in front of users
and learn whether they care.</p>
<p>Supabase gets you there faster. And when you&rsquo;re running solo, speed is everything.</p>
]]></content:encoded></item><item><title>The Hidden Tax Slowing Down Indie SaaS Builders</title><link>https://lakshminp.com/2025/10/indie-saas-hidden-tax/</link><pubDate>Mon, 13 Oct 2025 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2025/10/indie-saas-hidden-tax/</guid><category>essays</category><category>saas</category><description>We’ve been sold a lie — that every modern web app needs to be a “real app.”
You know the drill: a dedicated frontend built with React or Next.js, an API-only backend, and a separate database layer neatly tucked behind it.
It looks professional. It feels scalable.
But for indie developers building SaaS products, it’s a trap.
When you’re a solo founder or a two-person team trying to validate an idea, the 3-tier architecture — frontend + API + database — is rarely your friend.</description><content:encoded><![CDATA[<p>We’ve been sold a lie — that every modern web app needs to be a “real app.”</p>
<p>You know the drill: a dedicated frontend built with React or Next.js, an API-only backend, and a separate database layer neatly tucked behind it.</p>
<p>It looks professional. It feels scalable.</p>
<p>But for indie developers building SaaS products, it’s a trap.</p>
<p>When you’re a solo founder or a two-person team trying to validate an idea, the 3-tier architecture — <strong>frontend + API + database</strong> — is rarely your friend.</p>
<p>It’s a cognitive and operational tax disguised as “best practice.”</p>
<p>Think about what you’re actually doing when you follow this pattern:</p>
<ul>
<li>
<p>You spin up a frontend repo with its own dependencies, build system, routing, and deployment.</p>
</li>
<li>
<p>You spin up a backend API that must serialize, authenticate, and talk over HTTP just to move data between two systems you control.</p>
</li>
<li>
<p>You wire in your database and ORM, create migrations, and write serializers or DTOs to keep everyone happy.</p>
</li>
</ul>
<p>That’s three moving parts. Three deploys. Three layers of bugs.</p>
<p>For what?</p>
<p>Most MVPs don’t need “layers.” They need <strong>feedback.</strong></p>
<h2 id="the-3-tier-pattern-serves-organizations-not-builders"><strong>The 3-Tier Pattern Serves Organizations, Not Builders</strong></h2>
<p>Here’s the truth: this architecture exists to serve <em>org structure</em>, not product velocity.</p>
<p>Big companies need clear boundaries because they have teams:</p>
<ul>
<li>
<p>Frontend team</p>
</li>
<li>
<p>Backend team</p>
</li>
<li>
<p>Ops team</p>
</li>
</ul>
<p>The 3-tier pattern is basically Conway’s Law in code form — architecture mirroring the communication lines of large organizations.</p>
<p>But when you’re building your first SaaS, you <strong>are</strong> the team.</p>
<p>You don’t need boundaries between yourself. You need flow.</p>
<p>Every layer you add between user action and business logic slows that flow down. Every abstraction adds cognitive overhead. You spend more time plumbing than building.</p>
<h2 id="the-cognitive-overload-of-modern"><strong>The Cognitive Overload of “Modern”</strong></h2>
<p>React and friends were meant to solve complexity. Ironically, they’ve become a source of it.</p>
<p>A simple button click in React is rarely just a button click. It’s:</p>
<ul>
<li>
<p>A component that imports five dependencies.</p>
</li>
<li>
<p>A state hook managing a boolean.</p>
</li>
<li>
<p>A context provider that tracks global state.</p>
</li>
<li>
<p>An API call wrapped in a useEffect that must sync with local cache.</p>
</li>
</ul>
<p>You could’ve just written:</p>
<blockquote>
<p><code>&lt;button hx-post=”/like” hx-swap=”outerHTML”&gt;Like&lt;/button&gt;</code></p>
</blockquote>
<p>and been done with it.</p>
<p>React, Vue, Svelte — they’re incredible for rich UIs, but they demand constant context switching. JSX, state management, bundlers, APIs, hydration. Each decision compounds.</p>
<p>If your goal is to <strong>ship a paid product</strong>, not a code showcase, that complexity is friction.</p>
<h2 id="the-modern-backend-first-stack"><strong>The Modern “Backend-First” Stack</strong></h2>
<p>Choosing a simpler path doesn’t mean going back to sticks and stones.</p>
<p>HTML isn’t dead. It’s evolved.</p>
<p>You can build interactive, modern interfaces right inside your backend using tools like:</p>
<ul>
<li>
<p><strong>HTMX</strong> – progressive HTML-over-the-wire, no full reloads.</p>
</li>
<li>
<p><strong>Alpine.js</strong> – small, declarative reactivity.</p>
</li>
<li>
<p><strong>Tailwind CSS</strong> – utility-first design system that makes you fast <em>and</em> consistent.</p>
</li>
</ul>
<p>Together, they form a sweet spot:</p>
<ul>
<li>
<p>You write <strong>HTML templates</strong> with embedded actions.</p>
</li>
<li>
<p>You sprinkle <strong>JS</strong> only where it matters.</p>
</li>
<li>
<p>You serve it directly from your backend.</p>
</li>
</ul>
<p>No API layer. No hydration. No build pipeline. Just requests, responses, and users getting what they came for.</p>
<p>You still get interactivity, animations, modals, and dynamic UI updates — but with a tenth of the cognitive load.</p>
<p>This means faster iteration cycles, smaller deployments, and drastically fewer bugs.</p>
<p>Your stack lives in one repo.</p>
<p>Your deploy command is one line.</p>
<p>Your brainspace is freed up for actual product thinking.</p>
<h2 id="but-what-about-scaling"><strong>“But What About Scaling?”</strong></h2>
<p>That’s the wrong question for 95% of MVPs.</p>
<p>You don’t have a scaling problem until you have <em>users</em>.</p>
<p>Startups die from lack of traction, not lack of microservices.</p>
<p>If you ever outgrow this setup — great. Peel off layers later.</p>
<p>Turn your backend endpoints into APIs, move your UI to React, or even split your services. By then you’ll have revenue, validation, and real data to justify the refactor.</p>
<p>Premature architecture is just another form of procrastination.</p>
<h2 id="the-hidden-benefit-mental-clarity"><strong>The Hidden Benefit: Mental Clarity</strong></h2>
<p>Beyond performance and simplicity, there’s a more subtle gain: <strong>cognitive freedom.</strong></p>
<p>When your stack is unified, your brain can focus on the user flow instead of the glue code.</p>
<p>You can see everything — UI, logic, and data — in one place.</p>
<p>It feels cohesive.</p>
<p>You’re not juggling three languages, four toolchains, and two servers.</p>
<p>You’re just shipping.</p>
<p>And that matters more than any buzzword architecture ever will.</p>
<h2 id="the-takeaway-for-indie-saas-builders"><strong>The Takeaway for Indie SaaS Builders</strong></h2>
<p>You don’t get extra points for being complex.</p>
<p>You get rewarded for being useful.</p>
<p>A simpler stack means:</p>
<ul>
<li>
<p>Faster idea-to-demo time.</p>
</li>
<li>
<p>Easier onboarding if you add help later.</p>
</li>
<li>
<p>Fewer mental tabs open.</p>
</li>
<li>
<p>Lower hosting costs.</p>
</li>
<li>
<p>And most importantly — fewer excuses to delay launch.</p>
</li>
</ul>
<p>You can build 80% of what you think you need with plain HTML templates, Tailwind, and a bit of JS. Add Alpine for interactivity, HTMX for AJAX-like flow, and you’ll rival the speed of any React-Next duo out there.</p>
<p>Stop architecting for imaginary scale. Start shipping for real users.</p>
<p>Because the faster you close the gap between <em>idea</em> and <em>feedback</em>, the faster you learn, iterate, and make money.</p>
<p>And that’s the only scale that matters when you’re small.</p>
]]></content:encoded></item><item><title>How indie devs can vibe code fast without sinking their own ship</title><link>https://lakshminp.com/2025/10/vibe-code-fast-safely/</link><pubDate>Sun, 12 Oct 2025 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2025/10/vibe-code-fast-safely/</guid><category>essays</category><category>saas</category><category>ai-coding</category><description>There’s a quiet war inside every indie developer I know.
One part of you just wants to build.
To open the editor, follow your curiosity, and see something real come alive on screen.
That’s the vibe coder in you — the part that moves fast, trusts intuition, and believes momentum creates clarity.
Then there’s the other voice.
The one whispering about tests, migrations, rate limits, and all the invisible things that keep production from burning down.</description><content:encoded><![CDATA[<p>There’s a quiet war inside every indie developer I know.</p>
<p>One part of you just wants to <em>build</em>.</p>
<p>To open the editor, follow your curiosity, and see something real come alive on screen.</p>
<p>That’s the <strong>vibe coder</strong> in you — the part that moves fast, trusts intuition, and believes momentum creates clarity.</p>
<p>Then there’s the other voice.</p>
<p>The one whispering about tests, migrations, rate limits, and all the invisible things that keep production from burning down.</p>
<p>That’s the <strong>engineer</strong> in you — the part that’s seen systems crumble and knows “we’ll fix it later” often means “we’ll fix it never.”</p>
<p>Most of us swing between the two.</p>
<p>Too much vibe, and your SaaS turns into a spaghetti monster that terrifies future you.</p>
<p>Too much discipline, and you’ll design yourself into paralysis before your first user ever logs in.</p>
<p>The balance isn’t about finding the perfect middle ground — it’s about <strong>timing</strong>.</p>
<h2 id="phase-1-vibe-for-momentum"><strong>Phase 1: Vibe for Momentum</strong></h2>
<p>When you’re starting, you don’t need architecture.</p>
<p>You need <em>proof</em>. Proof that the idea resonates, that the workflow feels good, that you can sustain your own interest long enough to see it through.</p>
<p>Ship something messy.</p>
<p>Inline CSS. Hardcoded configs. A Docker Compose file running on your laptop.</p>
<p>If it helps you learn or get feedback faster, it’s good enough.</p>
<p>At this stage, your goal is to find the <em>pulse</em> of your product — the heartbeat that makes it worth polishing later.</p>
<h2 id="phase-2-add-discipline-for-survival"><strong>Phase 2: Add Discipline for Survival</strong></h2>
<p>Once someone uses it — or worse, depends on it — your job changes.</p>
<p>You’re no longer hacking; you’re maintaining.</p>
<p>That’s when guardrails matter.</p>
<p>Not enterprise-level bureaucracy, but the indie essentials:</p>
<p>rate limits, structured logs, CI checks, and a migration plan that won’t kill your data.</p>
<p>Each layer of success earns another layer of discipline.</p>
<p>That’s how you scale without killing your momentum.</p>
<h2 id="the-indie-balance"><strong>The Indie Balance</strong></h2>
<p>Vibe coding isn’t reckless.</p>
<p>It’s how you get to momentum.</p>
<p>But discipline is how you keep it.</p>
<p>The real art of indie software isn’t just writing good code.</p>
<p>It’s knowing <strong>when</strong> to write which kind of code.</p>
<p><strong>TL;DR:</strong></p>
<p>You start as an artist. You evolve into an engineer.</p>
<p>The trick is not to silence either voice — just let them take turns driving.</p>
]]></content:encoded></item><item><title>Why Your SaaS Needs a Docker Compose Setup Even If You’re Just One Person</title><link>https://lakshminp.com/2025/10/saas-docker-compose-setup/</link><pubDate>Fri, 10 Oct 2025 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2025/10/saas-docker-compose-setup/</guid><category>essays</category><category>kubernetes</category><category>saas</category><description>If you’re building a SaaS solo, the biggest productivity killer isn’t writing code — it’s setting up your damn environment.
You know the story:
You clone your repo on a new laptop or spin up a new dev box, run flask run or uvicorn main:app –reload, and boom — connection refused on localhost:5432.
Postgres isn’t running.
Your .env file is half missing.
Supabase changed a port.
And now you’re googling “how to reset a Postgres user password” for the third time this month.</description><content:encoded><![CDATA[<p>If you’re building a SaaS solo, the biggest productivity killer isn’t writing code — it’s <em>setting up your damn environment</em>.</p>
<p>You know the story:</p>
<p>You clone your repo on a new laptop or spin up a new dev box, run flask run or uvicorn main:app &ndash;reload, and boom — connection refused on localhost:5432.</p>
<p>Postgres isn’t running.</p>
<p>Your .env file is half missing.</p>
<p>Supabase changed a port.</p>
<p>And now you’re googling “how to reset a Postgres user password” for the third time this month.</p>
<p>That’s why I’ve stopped messing around with manual setups — and started containerizing my <em>local</em> environment using <strong>Docker Compose</strong>.</p>
<p>Not because it’s trendy.</p>
<p>Because it’s the only way to guarantee I can pull, build, and <em>run</em> my app in under a minute.</p>
<h2 id="the-indie-dev-reality"><strong>The indie dev reality</strong></h2>
<p>As solo devs, we move fast. We don’t have infra teams or onboarding docs. Most of our systems live in muscle memory and terminal history.</p>
<p>That’s fine when you’re in the groove — until you need to:</p>
<ul>
<li>
<p>Revisit a project after a few months.</p>
</li>
<li>
<p>Share it with a collaborator.</p>
</li>
<li>
<p>Spin it up on a new machine.</p>
</li>
<li>
<p>Or just fix a quick bug and realize nothing runs anymore.</p>
</li>
</ul>
<p>A solid local setup is like documentation that actually works.</p>
<p>Docker Compose is the simplest way to get there.</p>
<h2 id="why-docker-compose"><strong>Why Docker Compose?</strong></h2>
<p>It’s not about “microservices” or “container orchestration.” Ignore that stuff.</p>
<p>Compose is just a YAML file that says:</p>
<blockquote>
<p>“Here’s everything my app needs — run it all together.”</p>
</blockquote>
<p>You can define your web app, Postgres, and even Supabase’s local stack if you want to mirror production closely.</p>
<p>When you run docker compose up, everything spins up consistently — same versions, same ports, same config — every time.</p>
<p>It’s reproducibility for humans.</p>
<h2 id="the-minimal-example-python--postgres"><strong>The minimal example (Python + Postgres)</strong></h2>
<p>Let’s say you’re building a FastAPI app that talks to Postgres.</p>
<p>Here’s a dead-simple docker-compose.yml to make your life easier:</p>
<figure>
<a href="https://substackcdn.com/image/fetch/$s_!22g4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faadf5b35-ab7a-4b9e-b1b3-01f4109e1c1f_1180x1102.png" class="image-link image2 is-viewable-img" target="_blank" data-component-name="Image2ToDOM"></a>
<img src="https://substack-post-media.s3.amazonaws.com/public/images/aadf5b35-ab7a-4b9e-b1b3-01f4109e1c1f_1180x1102.png" class="sizing-normal" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aadf5b35-ab7a-4b9e-b1b3-01f4109e1c1f_1180x1102.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1102,&quot;width&quot;:1180,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:167377,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.lakshminp.com/i/175771487?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faadf5b35-ab7a-4b9e-b1b3-01f4109e1c1f_1180x1102.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" srcset="https://substackcdn.com/image/fetch/$s_!22g4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faadf5b35-ab7a-4b9e-b1b3-01f4109e1c1f_1180x1102.png 424w, https://substackcdn.com/image/fetch/$s_!22g4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faadf5b35-ab7a-4b9e-b1b3-01f4109e1c1f_1180x1102.png 848w, https://substackcdn.com/image/fetch/$s_!22g4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faadf5b35-ab7a-4b9e-b1b3-01f4109e1c1f_1180x1102.png 1272w, https://substackcdn.com/image/fetch/$s_!22g4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faadf5b35-ab7a-4b9e-b1b3-01f4109e1c1f_1180x1102.png 1456w" sizes="100vw" loading="lazy" width="1180" height="1102" />
<img src="data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld2JveD0iMCAwIDIwIDIwIiBmaWxsPSJub25lIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlPSJ2YXIoLS1jb2xvci1mZy1wcmltYXJ5KSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxnPjx0aXRsZT48L3RpdGxlPjxwYXRoIGQ9Ik0yLjUzMDAxIDcuODE1OTVDMy40OTE3OSA0LjczOTExIDYuNDMyODEgMi41IDkuOTExNzMgMi41QzEzLjE2ODQgMi41IDE1Ljk1MzcgNC40NjIxNCAxNy4wODUyIDcuMjM2ODRMMTcuNjE3OSA4LjY3NjQ3TTE3LjYxNzkgOC42NzY0N0wxOC41MDAyIDQuMjY0NzFNMTcuNjE3OSA4LjY3NjQ3TDEzLjY0NzMgNi45MTE3Nk0xNy40OTk1IDEyLjE4NDFDMTYuNTM3OCAxNS4yNjA5IDEzLjU5NjcgMTcuNSAxMC4xMTc4IDE3LjVDNi44NjExOCAxNy41IDQuMDc1ODkgMTUuNTM3OSAyLjk0NDMyIDEyLjc2MzJMMi40MTE2NSAxMS4zMjM1TTIuNDExNjUgMTEuMzIzNUwxLjUyOTMgMTUuNzM1M00yLjQxMTY1IDExLjMyMzVMNi4zODIyNCAxMy4wODgyIiAvPjwvZz48L3N2Zz4=" />
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld2JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLW1heGltaXplMiBsdWNpZGUtbWF4aW1pemUtMiI+PHBvbHlsaW5lIHBvaW50cz0iMTUgMyAyMSAzIDIxIDkiPjwvcG9seWxpbmU+PHBvbHlsaW5lIHBvaW50cz0iOSAyMSAzIDIxIDMgMTUiPjwvcG9seWxpbmU+PGxpbmUgeDE9IjIxIiB4Mj0iMTQiIHkxPSIzIiB5Mj0iMTAiPjwvbGluZT48bGluZSB4MT0iMyIgeDI9IjEwIiB5MT0iMjEiIHkyPSIxNCI+PC9saW5lPjwvc3ZnPg==" class="lucide lucide-maximize2 lucide-maximize-2" />
</figure>
<p><a href="https://gist.github.com/badri/43b709d1a62249464346609a740bb069" rel="external nofollow noopener" class="lnp-link">link to the gist</a></p>
<p>And a Dockerfile to go along with it.</p>
<figure>
<a href="https://substackcdn.com/image/fetch/$s_!-s5u!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25b6d76c-4d67-4ded-9c76-94738d7e2e9a_1298x1660.png" class="image-link image2 is-viewable-img" target="_blank" data-component-name="Image2ToDOM"></a>
<img src="https://substack-post-media.s3.amazonaws.com/public/images/25b6d76c-4d67-4ded-9c76-94738d7e2e9a_1298x1660.png" class="sizing-normal" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25b6d76c-4d67-4ded-9c76-94738d7e2e9a_1298x1660.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1660,&quot;width&quot;:1298,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:314313,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.lakshminp.com/i/175771487?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25b6d76c-4d67-4ded-9c76-94738d7e2e9a_1298x1660.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" srcset="https://substackcdn.com/image/fetch/$s_!-s5u!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25b6d76c-4d67-4ded-9c76-94738d7e2e9a_1298x1660.png 424w, https://substackcdn.com/image/fetch/$s_!-s5u!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25b6d76c-4d67-4ded-9c76-94738d7e2e9a_1298x1660.png 848w, https://substackcdn.com/image/fetch/$s_!-s5u!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25b6d76c-4d67-4ded-9c76-94738d7e2e9a_1298x1660.png 1272w, https://substackcdn.com/image/fetch/$s_!-s5u!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25b6d76c-4d67-4ded-9c76-94738d7e2e9a_1298x1660.png 1456w" sizes="100vw" loading="lazy" width="1298" height="1660" />
<img src="data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld2JveD0iMCAwIDIwIDIwIiBmaWxsPSJub25lIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlPSJ2YXIoLS1jb2xvci1mZy1wcmltYXJ5KSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxnPjx0aXRsZT48L3RpdGxlPjxwYXRoIGQ9Ik0yLjUzMDAxIDcuODE1OTVDMy40OTE3OSA0LjczOTExIDYuNDMyODEgMi41IDkuOTExNzMgMi41QzEzLjE2ODQgMi41IDE1Ljk1MzcgNC40NjIxNCAxNy4wODUyIDcuMjM2ODRMMTcuNjE3OSA4LjY3NjQ3TTE3LjYxNzkgOC42NzY0N0wxOC41MDAyIDQuMjY0NzFNMTcuNjE3OSA4LjY3NjQ3TDEzLjY0NzMgNi45MTE3Nk0xNy40OTk1IDEyLjE4NDFDMTYuNTM3OCAxNS4yNjA5IDEzLjU5NjcgMTcuNSAxMC4xMTc4IDE3LjVDNi44NjExOCAxNy41IDQuMDc1ODkgMTUuNTM3OSAyLjk0NDMyIDEyLjc2MzJMMi40MTE2NSAxMS4zMjM1TTIuNDExNjUgMTEuMzIzNUwxLjUyOTMgMTUuNzM1M00yLjQxMTY1IDExLjMyMzVMNi4zODIyNCAxMy4wODgyIiAvPjwvZz48L3N2Zz4=" />
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgdmlld2JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLW1heGltaXplMiBsdWNpZGUtbWF4aW1pemUtMiI+PHBvbHlsaW5lIHBvaW50cz0iMTUgMyAyMSAzIDIxIDkiPjwvcG9seWxpbmU+PHBvbHlsaW5lIHBvaW50cz0iOSAyMSAzIDIxIDMgMTUiPjwvcG9seWxpbmU+PGxpbmUgeDE9IjIxIiB4Mj0iMTQiIHkxPSIzIiB5Mj0iMTAiPjwvbGluZT48bGluZSB4MT0iMyIgeDI9IjEwIiB5MT0iMjEiIHkyPSIxNCI+PC9saW5lPjwvc3ZnPg==" class="lucide lucide-maximize2 lucide-maximize-2" />
</figure>
<p><a href="https://gist.github.com/badri/d198c94da28eae987cc2333b2f168d41" rel="external nofollow noopener" class="lnp-link">Link to the gist</a></p>
<p>That’s it.</p>
<p>Now you can run your entire stack with one command:</p>
<blockquote>
<p><code>docker compose up</code></p>
</blockquote>
<p>Your Python app connects to Postgres instantly.</p>
<p>No need to brew install, no weird port conflicts, no “is Postgres running?” guessing game.</p>
<h2 id="want-to-mirror-supabase-locally"><strong>Want to mirror Supabase locally?</strong></h2>
<p>If you’re using <strong>Supabase</strong> in production but want to run locally, Supabase has its own CLI that uses Docker under the hood.</p>
<p>You can spin up a near-production clone with:</p>
<blockquote>
<p><code>supabase start</code></p>
</blockquote>
<p>That’ll run Postgres, API, auth, and storage locally in containers — no manual setup required.</p>
<p>It’s heavier, but it’s great if you’re testing row-level security, triggers, or anything that depends on Supabase’s stack.</p>
<h2 id="but-isnt-docker-heavy"><strong>But isn’t Docker heavy?</strong></h2>
<p>Yeah, a little.</p>
<p>The first time you pull images, it’ll download a few hundred MB. After that, it’s fast.</p>
<p>And honestly, the alternative is worse — debugging inconsistent environments and broken local databases.</p>
<p>The real magic isn’t that it’s fast — it’s that it’s <em>reliable</em>.</p>
<p>If you take a break from your project for a month, you can come back and it’ll just work.</p>
<p>That’s worth the disk space.</p>
<h2 id="bonus-the-same-setup-works-for-production"><strong>Bonus: the same setup works for production</strong></h2>
<p>Here’s the underrated part — once you have this docker-compose.yml, you’re halfway to a production deployment.</p>
<p>You can:</p>
<ul>
<li>
<p>Build your app image with docker compose build api.</p>
</li>
<li>
<p>Push it to a registry like Docker Hub or GitHub Container Registry.</p>
</li>
<li>
<p>Deploy it to Fly.io, Render, Railway, or your VPS — all of which happily accept a pre-built Docker image.</p>
</li>
</ul>
<p>That means your <strong>local setup = production setup</strong>.</p>
<p>No “works on my machine,” no separate Heroku config, no hand-tuned server differences.</p>
<p>You’re testing <em>exactly</em> what you’ll ship.</p>
<p>For example, to build your image for deployment:</p>
<blockquote>
<p><code>docker compose build api</code></p>
<p><code>docker tag yourapp_api your-registry.com/yourapp:latest</code></p>
<p><code>docker push your-registry.com/yourapp:latest</code></p>
</blockquote>
<p>Then you can run it anywhere with:</p>
<blockquote>
<p><code>docker run -p 8000:8000 your-registry.com/yourapp:latest</code></p>
</blockquote>
<p>This alignment — same Dockerfile, same Compose config — is what makes deployment predictable, even as a one-person team.</p>
<h2 id="quality-of-life-improvements"><strong>Quality-of-life improvements</strong></h2>
<p>Once you’ve got Compose running smoothly, you can make it even nicer:</p>
<p><strong>1. Add a Makefile or script for one-command startup:</strong></p>
<blockquote>
<p><code>make up</code></p>
</blockquote>
<p>Your Makefile contents:</p>
<blockquote>
<p><code>up:</code></p>
<p><code> docker compose up --build</code></p>
</blockquote>
<p><strong>2. Add a seed script for your DB:</strong></p>
<blockquote>
<p><code>docker compose exec db psql -U dev -d app -f seeds.sql</code></p>
</blockquote>
<p><strong>3. Run tests in the same containers:</strong></p>
<blockquote>
<p><code>docker compose run api pytest</code></p>
</blockquote>
<p>You now have a full, consistent local dev environment that <em>feels like production</em>, without the cloud bill.</p>
<h2 id="the-point-isnt-docker--its-repeatability"><strong>The point isn’t Docker — it’s repeatability</strong></h2>
<p>You’re not doing this to “learn containers.”</p>
<p>You’re doing it because your time is too valuable to waste on setup chores.</p>
<p>A docker-compose.yml file is the indie dev version of a safety net.</p>
<p>You can drop your laptop, clone your repo on a new one, and be productive in 60 seconds flat.</p>
<p>And when it’s time to deploy?</p>
<p>You’re already 90% there.</p>
<h2 id="tldr"><strong>TL;DR</strong></h2>
<ul>
<li>
<p>Your SaaS deserves a repeatable local setup.</p>
</li>
<li>
<p>Docker Compose makes it dead simple for Python + Postgres (and Supabase).</p>
</li>
<li>
<p>It doubles as your build foundation for production images.</p>
</li>
<li>
<p>You’ll thank yourself every time you reopen an old project or deploy something new.</p>
</li>
</ul>
<p>It’s one of those rare decisions that’s both practical <em>and</em> future-proof.</p>
<p>Set it up once — and your dev-to-prod pipeline just became a lot less fragile.</p>
]]></content:encoded></item><item><title>Stop Forcing Subscriptions on your SaaS. Do this instead.</title><link>https://lakshminp.com/2025/10/saas-one-time-pricing/</link><pubDate>Thu, 09 Oct 2025 00:00:00 +0000</pubDate><author>Lakshmi Narasimhan</author><guid isPermaLink="true">https://lakshminp.com/2025/10/saas-one-time-pricing/</guid><category>essays</category><category>saas</category><description>For the past decade, “SaaS” has been almost synonymous with “subscription.”
Monthly plans. Recurring revenue. The holy grail of predictability.
But let’s be honest — not every product justifies being billed every month.
Some tools solve a short, sharp problem. They’re used heavily once, and then only occasionally, if ever, after that.
Forcing that into a subscription model doesn’t create a loyal customer base. It creates churn.
So, let’s talk about an alternative: a one-time license model that’s installed on the user’s own infrastructure.</description><content:encoded><![CDATA[<p>For the past decade, “SaaS” has been almost synonymous with “subscription.”<br>
Monthly plans. Recurring revenue. The holy grail of predictability.</p>
<p>But let’s be honest — not every product justifies being billed every month.<br>
Some tools solve a short, sharp problem. They’re used heavily once, and then only occasionally, if ever, after that.</p>
<p>Forcing that into a subscription model doesn’t create a loyal customer base. It creates churn.</p>
<p>So, let’s talk about an alternative: <strong>a one-time license model that’s installed on the user’s own infrastructure</strong>.</p>
<p>They buy it once. You give them the code. They run it wherever they want.</p>
<p>It’s not just a throwback to the old “software license” days — it’s a modern, lean, developer-friendly way to build a business without the overhead of hosting, scaling, and endless retention tactics.</p>
<h2 id="when-subscriptions-dont-fit">When Subscriptions Don’t Fit</h2>
<p>Imagine you’ve built a tool that helps teams <strong>migrate their customer data from one CRM to another</strong>.</p>
<p>Most companies only do this once. They just want it done right.</p>
<p>You could sell this as a $49/month SaaS, but that’s immediately awkward:</p>
<ul>
<li>
<p>Your users might only need it for a few weeks.</p>
</li>
<li>
<p>You’ll end up with tons of churn.</p>
</li>
<li>
<p>You’ll need to support inactive users forever because “they’re still subscribed.”</p>
</li>
</ul>
<p>Now imagine instead you sell it as a <strong>one-time installable tool</strong>.</p>
<p>They pay <strong>$499</strong> upfront. You send them the source (or a compiled binary) and a license key. They run it on their own infra — AWS, GCP, their laptop, whatever.</p>
<p>No ongoing hosting costs for you.<br>
No surprise bills for them.<br>
No monthly churn charts haunting you.</p>
<p>Just a clean, value-aligned exchange: <em>they pay for the outcome; you deliver it.</em></p>
<h2 id="but-isnt-that-giving-away-the-code">But Isn’t That Giving Away the Code?</h2>
<p>Yes — and that’s not as scary as it sounds.</p>
<p>For technical customers (especially startups or agencies), <strong>self-hosted + licensed</strong> software can be a big <em>selling point</em>. They get control, compliance, and peace of mind.</p>
<p>And for you? You skip the DevOps, uptime monitoring, and scaling headaches.</p>
<p>You can even <strong>open-source a limited version</strong> and sell the “Pro” edition with additional features, integrations, or automation. That approach builds trust and lowers the barrier to entry — a model proven by countless successful tools (think Plausible, Sentry, or PostHog).</p>
<h2 id="how-to-make-it-profitable-without-recurring-revenue">How to Make It Profitable (Without Recurring Revenue)</h2>
<p>Let’s be real: one-time payments can kill you if you don’t plan for longevity.</p>
<p>You can’t promise lifetime updates for $49 and expect to survive.<br>
The trick is to <strong>price for sustainability</strong> and design smart upsells.</p>
<p>Here’s a simple structure:</p>
<ol>
<li>
<p><strong>Base License (One-Time Purchase)</strong><br>
The core product, installable and self-managed. One license per company, priced based on business value — not your costs.<br>
Example: $499 for the migration tool.</p>
</li>
<li>
<p><strong>Pro or Enterprise Tier</strong><br>
Unlocks advanced features like API access, audit logs, or multi-user setups.<br>
Example: $1,499 for the “Enterprise Migration Suite.”</p>
</li>
<li>
<p><strong>Done-for-You Setup</strong><br>
Not everyone wants to fiddle with YAML files or AWS permissions. Offer to set it up for them — fast, clean, and guaranteed to work.<br>
Example: $1,000 for installation and configuration.</p>
</li>
<li>
<p><strong>Support Retainer (Recurring)</strong><br>
For customers who <em>do</em> want ongoing help, offer an optional support plan — monthly or yearly — that they can cancel anytime.<br>
Example: $200/month for priority support and updates.</p>
</li>
<li>
<p><strong>Fixed Support Packages</strong><br>
For those who prefer predictability, offer prepaid support hours.<br>
Example: $800 for 10 hours of support, usable anytime within a year.</p>
</li>
</ol>
<p>The combination of these makes your business sustainable.<br>
You get upfront cash flow from licenses and setups, and optional recurring revenue from support — but without forcing subscriptions on everyone.</p>
<h2 id="a-real-example-indie-data-migration-tool">A Real Example: Indie Data Migration Tool</h2>
<p>Let’s run the numbers.</p>
<p>You sell a <strong>self-hosted data migration tool</strong>.<br>
You price it at <strong>$499</strong> for the standard license.</p>
<p>In your first month, 10 teams buy it. That’s <strong>$4,990 upfront</strong>.</p>
<p>Out of those, 3 ask for the done-for-you setup at $1,000 each.<br>
Now you’re at <strong>$7,990</strong> total.</p>
<p>Two of those teams also sign up for your support retainer at $200/month.</p>
<p>That’s an extra <strong>$400 MRR</strong> — but it’s optional, not forced.</p>
<p>You’ve built something simple, useful, and profitable — without ever worrying about churn graphs, Stripe retries, or feature bloat to “increase stickiness.”</p>
<h2 id="actionable-takeaways">Actionable Takeaways</h2>
<p><strong>Match pricing to value, not format.</strong><br>
Don’t just copy the subscription playbook because everyone else does. Ask yourself: how often will people actually use this thing, and how much pain does it remove? If it’s a one-time fix, charge like it.</p>
<p><strong>Design for autonomy.</strong><br>
Developers love control. Let them host it, own it, and plug it into their stack. You’ll end up with happier customers and fewer support tickets than you’d think.</p>
<p><strong>Price like it matters.</strong><br>
If you’re selling a one-time license, it needs to <em>cover your runway</em>. Don’t shy away from bigger numbers. $499 for something that works beats $49/month for something people cancel in two.</p>
<p><strong>Offer optional continuity.</strong><br>
You don’t have to force subscriptions, but you can still offer them. A support retainer or yearly update plan gives your best customers a way to stay connected — and gives you breathing room.</p>
<p><strong>Keep it simple.</strong><br>
No servers, no churn dashboards, no “engagement loops.” Just build a tool, sell it, and support the people who need it. That’s still a business — and a pretty good one.</p>
<p>In a world obsessed with “monthly recurring revenue,” it’s refreshing to remember you can still build a <strong>sane, sustainable business</strong> by selling software the old-fashioned way — for a fair, one-time price.</p>
<p>Sometimes, the best “recurring” part of your business isn’t the billing.<br>
It’s your reputation for shipping solid tools that solve real problems.</p>
]]></content:encoded></item></channel></rss>