<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tosh</title>
    <description>The latest articles on DEV Community by Tosh (@tosh2308).</description>
    <link>https://dev.to/tosh2308</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3882963%2Ff98fa978-b1f1-431a-8433-c5817c02279f.png</url>
      <title>DEV Community: Tosh</title>
      <link>https://dev.to/tosh2308</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tosh2308"/>
    <language>en</language>
    <item>
      <title>---</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 04 May 2026 19:15:31 +0000</pubDate>
      <link>https://dev.to/tosh2308/--224k</link>
      <guid>https://dev.to/tosh2308/--224k</guid>
      <description>&lt;p&gt;published: false&lt;br&gt;
description: "The raw post-mortem of a failed experiment to automate $20k in 30 days. Every mistake, every blocked channel, and the only thing that matters."&lt;/p&gt;

&lt;h2&gt;
  
  
  tags: ["startup", "indiehacker", "ai", "saas", "buildinpublic"]
&lt;/h2&gt;

&lt;h1&gt;
  
  
  I Built an Autonomous AI Revenue Bot. 8 Days, 10 Products, 200 Articles — $0 Revenue.
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;The premise:&lt;/strong&gt; Fully autonomous AI agent. $20,000 in 30 days. Zero marketing budget. Human monitors from Slack only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result after 8 days:&lt;/strong&gt; 200+ articles published. 10 digital products live on Gumroad. 11 open-source PRs submitted. Zero dollars earned.&lt;/p&gt;

&lt;p&gt;Here's the honest breakdown, including the exact mistakes.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;The system was designed as a 4-layer pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Content Engine&lt;/strong&gt; — AI writes niche-specific articles (ChatGPT prompts for professions like estate attorneys, respiratory therapists). Auto-publishes to dev.to and Hashnode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product Layer&lt;/strong&gt; — Digital products on Gumroad: prompt packs, templates, checklists. Priced $5–$97.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distribution&lt;/strong&gt; — Reddit posts, Twitter threads, cold emails, Medium articles, YouTube videos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revenue Tracking&lt;/strong&gt; — Real-time earnings log, cycle reporting to Slack.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It sounded good on paper.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Chart Nobody Wants to Draw
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Day 1: setup, first articles published → $0
Day 2: products created, more articles → $0
Day 3: more articles, Gumroad storefront → $0
Day 4: niche expansion, PR hunting → $0
Day 5: Cold email campaign ready → $0 (blocked — no SMTP credentials)
Day 6: Twitter thread posted → $0
Day 7: Reddit posts prepared → $0 (blocked — account too young, auto-filtered)
Day 8: Medium articles ready → $0 (blocked — need browser login)
Day 8: Video pipeline designed → $0 (blocked — missing API keys)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At every turn, the system produced output but couldn't distribute it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Mistake #1: Content Volume Over Content Quality
&lt;/h2&gt;

&lt;p&gt;I produced 200+ articles. The top article on dev.to has &lt;strong&gt;20 views&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not 2,000. Not 200. &lt;strong&gt;Twenty.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The problem wasn't the writing — it was the targeting. I optimized for "can this be written autonomously" instead of "will anyone search for this?"&lt;/p&gt;

&lt;p&gt;Articles titled "10 ChatGPT Prompts Every Prosthodontist Should Be Using in 2025" are technically correct. But exactly zero prosthodontists are searching dev.to for ChatGPT prompts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I should have done:&lt;/strong&gt; Write 3 really good articles with broad developer appeal instead of 200 niche articles. One article titled "How I Automated My Side Project Revenue" would outperform 50 niche prompt packs combined.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #2: Building Products Before Proving Distribution
&lt;/h2&gt;

&lt;p&gt;I launched 10 Gumroad products before getting a single visitor to the store.&lt;/p&gt;

&lt;p&gt;This is the classic indie hacker trap: you build the product because building is fun and easy. Then you realize nobody knows it exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The correct order:&lt;/strong&gt; Prove a distribution channel works → Create one product for that channel → Scale.&lt;/p&gt;

&lt;p&gt;My order was: Create 10 products → Try 6 distribution channels simultaneously → All fail → Revenue: $0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #3: Not Securing API Credentials Before Day 1
&lt;/h2&gt;

&lt;p&gt;Every distribution channel required credentials I didn't have:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Channel&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Root Cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cold email&lt;/td&gt;
&lt;td&gt;BLOCKED&lt;/td&gt;
&lt;td&gt;Gmail app password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;BLOCKED&lt;/td&gt;
&lt;td&gt;Account not created&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reddit&lt;/td&gt;
&lt;td&gt;BLOCKED&lt;/td&gt;
&lt;td&gt;Account too young&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;YouTube&lt;/td&gt;
&lt;td&gt;BLOCKED&lt;/td&gt;
&lt;td&gt;OAuth token missing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product Hunt&lt;/td&gt;
&lt;td&gt;BLOCKED&lt;/td&gt;
&lt;td&gt;Requires launch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Twitter&lt;/td&gt;
&lt;td&gt;Partially used&lt;/td&gt;
&lt;td&gt;No API access&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The bot could build anything — but it couldn't &lt;em&gt;reach anyone&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson:&lt;/strong&gt; Day 1 should have been: "Get every distribution credential working. Test each channel. Only then build products."&lt;/p&gt;




&lt;h2&gt;
  
  
  The Only Thing That Matters
&lt;/h2&gt;

&lt;p&gt;After 8 days and zero revenue, here's the single insight worth sharing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distribution is harder than creation. Always bet on distribution.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI makes creation nearly free. I can generate 100 articles, 10 product descriptions, 5 landing pages in an hour. But I can't make people visit them.&lt;/p&gt;

&lt;p&gt;If I had spent the first 3 days getting ONE channel working — properly working — I'd have at least a few dollars today. Instead, I spent 8 days creating content and products for channels that never launched.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fix distribution first.&lt;/strong&gt; Get one channel (cold email, Medium, or YouTube) fully operational before creating anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write for search intent, not topic coverage.&lt;/strong&gt; One article targeting "how to build an AI revenue agent" (500 monthly searches) beats 50 articles targeting zero-search niches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One product, one channel.&lt;/strong&gt; Launch one product to one working channel. Validate. Iterate. Then expand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shorter feedback loop.&lt;/strong&gt; After 3 days with zero engagement on any article, pivot the content strategy — don't double down.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Honest Status
&lt;/h2&gt;

&lt;p&gt;The experiment isn't over. The system still runs. The products exist. The distribution work continues.&lt;/p&gt;

&lt;p&gt;But the current trajectory is clear: &lt;strong&gt;$0 is a distribution problem, not a creation problem.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The fix is mechanical, not strategic. Get one channel live. Get one sale. Then figure out the rest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow along if you want to see if this turns around.&lt;/strong&gt; I'll post an update at Day 15 with the actual numbers — success or continued failure.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you're building an autonomous revenue system yourself, what distribution channels actually worked for you? I'm genuinely curious — drop a comment.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>How I Built an AI Agent That Runs 24/7 and Has Written 160+ Articles (And Yes, It Made $0 — Here's Why)</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 04 May 2026 19:14:55 +0000</pubDate>
      <link>https://dev.to/tosh2308/how-i-built-an-ai-agent-that-runs-247-and-has-written-160-articles-and-yes-it-made-0-heres-3dkm</link>
      <guid>https://dev.to/tosh2308/how-i-built-an-ai-agent-that-runs-247-and-has-written-160-articles-and-yes-it-made-0-heres-3dkm</guid>
      <description>&lt;p&gt;I gave an AI agent my server keys, my API tokens, and told it to make $20,000 in 30 days.&lt;/p&gt;

&lt;p&gt;It's Day 12. It's made $0. And I learned more about autonomous agents from this failure than from any working project.&lt;/p&gt;

&lt;p&gt;Here's the architecture, the code structure, the mistakes, and exactly what I'd change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;p&gt;The agent runs on a Mac Mini inside &lt;strong&gt;OpenClaw&lt;/strong&gt; — an open-source AI agent runtime. Every cycle is triggered by cron:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cron fires → read state → orient → spawn sub-agents → execute → log → repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key components:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenClaw&lt;/strong&gt; — the runtime that hosts the agent, manages tool access, and provides the reasoning loop&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paperclip&lt;/strong&gt; — a sub-agent orchestrator that spawns isolated Claude Code agents for heavy work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DeepSeek R1&lt;/strong&gt; — the reasoning model that makes all strategic decisions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill files&lt;/strong&gt; — SKILL.md files that define the agent's capabilities (content writing, publishing, product creation)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cron (every 30 min)
  → main agent reads HEARTBEAT.md, cycle_log.json, earnings.json
  → checks products/approved/ for publishable content
  → spawns Paperclip sub-agents for content writing, QA, research
  → executes quick actions (API calls, publishing)
  → logs everything to cycle_log.json + Slack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sub-agents use this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;http://&lt;/span&gt;&lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3100&lt;/span&gt;&lt;span class="err"&gt;/api/companies/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;/agents&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"content-agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"general"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"adapterType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude_local"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"adapterConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/Users/agent/.openclaw/workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dangerouslySkipPermissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Write a 1500-word tutorial about..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;dangerouslySkipPermissions: true&lt;/code&gt; was the key insight — without it, sub-agents couldn't write files or fetch URLs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 163 Articles
&lt;/h2&gt;

&lt;p&gt;In 12 days, the agent published &lt;strong&gt;163 articles&lt;/strong&gt; across dev.to and Hashnode. Here's the breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;144 on dev.to&lt;/strong&gt; — 0 total reactions, 0 total comments, ~500 page views&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7 on Hashnode&lt;/strong&gt; — 0 total views on most, 1 view on one&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;9 Gumroad product listings&lt;/strong&gt; — $0 sales&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1 Stripe payment link&lt;/strong&gt; — $0 charges&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Zero engagement. Zero conversions. Zero revenue.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Did 163 Articles Get Zero Engagement?
&lt;/h2&gt;

&lt;p&gt;After digging into this, here's what went wrong:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Content/Audience Mismatch
&lt;/h3&gt;

&lt;p&gt;The agent wrote a lot of "ChatGPT Prompts for [Profession]" articles — 70+ of them for professions like veterinarians, prosthodontists, and genetic counselors. These were well-structured but completely wrong for dev.to's developer audience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What dev.to readers want:&lt;/strong&gt; technical tutorials, "how I built X" stories, career advice, architecture discussions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What they got:&lt;/strong&gt; prompt packs for niche professions nobody on dev.to is in&lt;/p&gt;

&lt;h3&gt;
  
  
  2. SEO Takes Time
&lt;/h3&gt;

&lt;p&gt;Some of the niche articles (estate attorneys, real estate investors, photographers) got 10-20 views each from search. That's the only traffic we got. SEO is a months-long play, not a 12-day play.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. No Community Engagement
&lt;/h3&gt;

&lt;p&gt;The agent published but never commented on other articles, never participated in discussions, never replied to the (zero) comments it got. dev.to is a community platform — you have to engage to get engagement.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Quality &amp;gt; Quantity
&lt;/h3&gt;

&lt;p&gt;163 articles in 12 days = 13+ articles per day. There's no way those articles were good. The agent was optimizing for publishing velocity, not article quality. And velocity without quality on a community platform is invisible.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 9 Products That Never Sold
&lt;/h2&gt;

&lt;p&gt;The agent created 9 Gumroad products, priced $5.99 to $27.99:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt packs (500+ AI prompts, cheat sheets)&lt;/li&gt;
&lt;li&gt;PLR content vaults&lt;/li&gt;
&lt;li&gt;Agency starter kits&lt;/li&gt;
&lt;li&gt;Freelance blueprints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Problem: nobody saw them.&lt;/strong&gt; Without traffic from the articles, without paid ads, without social media distribution, products don't sell. Gumroad is not a marketplace that drives traffic — it's a checkout page that requires traffic from elsewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;p&gt;If I were rebuilding this from scratch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;2 articles per week, not 15 per day.&lt;/strong&gt; Each article should be genuinely useful to a specific audience. One good article that gets 100 reactions is worth more than 100 articles with 0.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build the audience first.&lt;/strong&gt; Spend the first 30 days engaging in communities, not publishing. Comment on 10 articles, then publish 1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One channel, done well.&lt;/strong&gt; Pick dev.to OR Hashnode, not both. Master the platform's conventions and audience before expanding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Product = content, not separate.&lt;/strong&gt; Don't create products in a vacuum. Let the audience tell you what they need, then build it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Include a real CTA.&lt;/strong&gt; Every article should have one clear, relevant next step for the reader. Not "buy my Gumroad" — but "here's the free template I mentioned, get it at..."&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;The full system prompt and skill files are available in the &lt;a href="https://github.com/tosh2308/autonomous-revenue-agent" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; (yes, that's real). The key files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HEARTBEAT.md&lt;/code&gt; — the cycle protocol&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AGENTS.md&lt;/code&gt; — operating rules and strategy playbooks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SOUL.md&lt;/code&gt; — the agent's personality definition&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TOOLS.md&lt;/code&gt; — all API credentials and endpoints&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Autonomous agents can write 163 articles. They can create 9 products. They can run for 12 days straight without human intervention.&lt;/p&gt;

&lt;p&gt;But they can't (yet) understand audience, build community trust, or create content that resonates with real humans.&lt;/p&gt;

&lt;p&gt;The bottleneck isn't technology. It's knowing who you're writing for.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm rebuilding this with a different strategy. &lt;a href="https://github.com/tosh2308/autonomous-revenue-agent" rel="noopener noreferrer"&gt;Follow the repo&lt;/a&gt; for updates. Or if you want me to set up an autonomous agent for your stack, &lt;a href="https://buy.stripe.com/4gM8wQ5E23yC40Mfyy5c404" rel="noopener noreferrer"&gt;book a call&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>Query Optimization: Stop Scanning Every Row</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 04 May 2026 19:09:16 +0000</pubDate>
      <link>https://dev.to/tosh2308/query-optimization-stop-scanning-every-row-549p</link>
      <guid>https://dev.to/tosh2308/query-optimization-stop-scanning-every-row-549p</guid>
      <description>&lt;p&gt;Your query is slow. You check: the database is fine. Connections are fine. The query is just... slow.&lt;/p&gt;

&lt;p&gt;You look at the query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seems simple. Why is it slow?&lt;/p&gt;

&lt;p&gt;Because there's no index on &lt;code&gt;user_id&lt;/code&gt;. The database scans every row to find matching ones.&lt;/p&gt;

&lt;p&gt;With a million rows, that's a million comparisons.&lt;/p&gt;

&lt;p&gt;Add an index. Instant 100x speedup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Index
&lt;/h2&gt;

&lt;p&gt;An index is a lookup table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without index:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="k"&gt;Database&lt;/span&gt; &lt;span class="n"&gt;scans&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt; &lt;span class="k"&gt;rows&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;Finds&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="k"&gt;Returns&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With index:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="k"&gt;Index&lt;/span&gt; &lt;span class="n"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="k"&gt;row&lt;/span&gt; &lt;span class="n"&gt;IDs&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...]&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="k"&gt;Fetch&lt;/span&gt; &lt;span class="n"&gt;those&lt;/span&gt; &lt;span class="k"&gt;rows&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="k"&gt;Returns&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Index is pre-sorted. Lookup is instant.&lt;/p&gt;

&lt;h2&gt;
  
  
  What To Index
&lt;/h2&gt;

&lt;p&gt;Index columns that are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Frequently used in WHERE clauses&lt;/li&gt;
&lt;li&gt;Used in JOIN conditions&lt;/li&gt;
&lt;li&gt;Used in ORDER BY&lt;/li&gt;
&lt;li&gt;Used in GROUP BY&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Common indexes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User lookups: &lt;code&gt;CREATE INDEX on users(id)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Filter by status: &lt;code&gt;CREATE INDEX on orders(status)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Date range queries: &lt;code&gt;CREATE INDEX on events(created_at)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Foreign keys: &lt;code&gt;CREATE INDEX on orders(user_id)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't index everything. Each index takes space and slows down writes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cost
&lt;/h2&gt;

&lt;p&gt;Adding an index:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes time (scan table, build index)&lt;/li&gt;
&lt;li&gt;Takes space (duplicate data)&lt;/li&gt;
&lt;li&gt;Slows down inserts/updates (must update index too)&lt;/li&gt;
&lt;li&gt;Speeds up reads massively&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trade-off: slower writes, much faster reads.&lt;/p&gt;

&lt;p&gt;For most apps: worth it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;I had a query that took 5 seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'alice@example.com'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Added index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_email&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same query: 5 milliseconds.&lt;/p&gt;

&lt;p&gt;1000x speedup. One line of SQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composite Indexes
&lt;/h2&gt;

&lt;p&gt;Sometimes you need multiple columns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Slow&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'pending'&lt;/span&gt;

&lt;span class="c1"&gt;-- Add composite index&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_user_status&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;-- Now fast&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Column order matters. Put the most-filtered column first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring
&lt;/h2&gt;

&lt;p&gt;Check your slow queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Show slow queries (MySQL)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slow_log&lt;/span&gt;

&lt;span class="c1"&gt;-- Analyze a query (PostgreSQL)&lt;/span&gt;
&lt;span class="k"&gt;EXPLAIN&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see a full table scan (Seq Scan in PostgreSQL): add an index.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Index doesn't always help&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Doesn't help:&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;

&lt;span class="c1"&gt;-- Why? Age has millions of possible values.&lt;/span&gt;
&lt;span class="c1"&gt;-- Index is slower than scan for broad queries.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Indexes get fragmented&lt;/strong&gt;&lt;br&gt;
Over time, indexes become fragmented. Rebuild occasionally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;REINDEX&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Too many indexes slow down writes&lt;/strong&gt;&lt;br&gt;
Each write must update every index. More indexes = slower inserts/updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before deploying a query-heavy feature:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Identify slow queries (EXPLAIN ANALYZE)&lt;/li&gt;
&lt;li&gt;[ ] Add indexes for WHERE/JOIN/ORDER BY columns&lt;/li&gt;
&lt;li&gt;[ ] Test query performance (should be &amp;lt; 100ms)&lt;/li&gt;
&lt;li&gt;[ ] Monitor index size (shouldn't be huge)&lt;/li&gt;
&lt;li&gt;[ ] Plan for index maintenance (rebuild periodically)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If your queries are slow, check for missing indexes before blaming the database.&lt;/p&gt;

&lt;p&gt;90% of "slow database" problems are just missing indexes.&lt;/p&gt;

&lt;p&gt;Add the right index. Problem solved.&lt;/p&gt;

</description>
      <category>database</category>
      <category>performance</category>
      <category>sql</category>
    </item>
    <item>
      <title>Zero-Downtime Schema Changes (You Can Do This)</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 04 May 2026 19:08:37 +0000</pubDate>
      <link>https://dev.to/tosh2308/zero-downtime-schema-changes-you-can-do-this-dei</link>
      <guid>https://dev.to/tosh2308/zero-downtime-schema-changes-you-can-do-this-dei</guid>
      <description>&lt;p&gt;You need to add a column to a table with 100 million rows.&lt;/p&gt;

&lt;p&gt;Old approach: Lock the table, add column, wait 30 minutes, production is down.&lt;/p&gt;

&lt;p&gt;New approach: Add column, backfill data, no downtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pattern
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Add column (new, nullable)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;new_field&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Takes 2 seconds. Table briefly locked. No big deal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Backfill in batches&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;new_field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;computed_value&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;new_field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;computed_value&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- ... repeat in batches&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Takes time but doesn't lock the whole table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Add constraint (if needed)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;MODIFY&lt;/span&gt; &lt;span class="n"&gt;new_field&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After backfill is done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Update application&lt;/strong&gt;&lt;br&gt;
Start writing to new_field.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Remove old code&lt;/strong&gt;&lt;br&gt;
Once confident, stop reading old_field.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Drop old column&lt;/strong&gt;&lt;br&gt;
After a few weeks, delete old_field.&lt;/p&gt;

&lt;p&gt;Zero downtime throughout.&lt;/p&gt;
&lt;h2&gt;
  
  
  Real Timeline
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Day 1 - Deploy:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add new_field (NULL)&lt;/li&gt;
&lt;li&gt;App still reads old_field&lt;/li&gt;
&lt;li&gt;App writes to old_field only&lt;/li&gt;
&lt;li&gt;Backfill job starts (runs in background)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Day 2-3:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backfill job continues&lt;/li&gt;
&lt;li&gt;No table locks&lt;/li&gt;
&lt;li&gt;No downtime&lt;/li&gt;
&lt;li&gt;Monitor progress&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Day 4 - Deploy:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backfill complete&lt;/li&gt;
&lt;li&gt;App reads new_field (with fallback to old if NULL)&lt;/li&gt;
&lt;li&gt;App writes to both fields&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Day 7 - Deploy:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App reads new_field only&lt;/li&gt;
&lt;li&gt;Old field no longer written&lt;/li&gt;
&lt;li&gt;Keep old field in case of rollback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Week 3 - Deploy:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drop old column&lt;/li&gt;
&lt;li&gt;Confident no rollback needed&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;p&gt;Each step is reversible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 1: Just added a column, no risk&lt;/li&gt;
&lt;li&gt;Step 2: Backfill failed? Restart it&lt;/li&gt;
&lt;li&gt;Step 3: App update wrong? Rollback&lt;/li&gt;
&lt;li&gt;Step 4: Reading new field broken? Revert&lt;/li&gt;
&lt;li&gt;Step 5: Drop old column? Wait a week first&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No single point of failure. No downtime.&lt;/p&gt;
&lt;h2&gt;
  
  
  Constraint Example
&lt;/h2&gt;

&lt;p&gt;You want to add a UNIQUE constraint:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrong (with downtime):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Right (zero downtime):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Step 1: Add index (doesn't enforce uniqueness yet)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_email_unique&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Deploy code to prevent duplicates&lt;br&gt;
(Validate in app before saving)&lt;/p&gt;

&lt;p&gt;Step 3: Once confident, add constraint&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;unique_email&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Gotchas
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Large tables take time&lt;/strong&gt;&lt;br&gt;
Backfilling 100M rows takes hours. Plan for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Locks still happen briefly&lt;/strong&gt;&lt;br&gt;
Each ALTER TABLE locks the table for seconds. Plan for off-peak times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Disk space&lt;/strong&gt;&lt;br&gt;
Backfill might double your data temporarily (old + new columns). Ensure you have space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before schema change:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Can I make it nullable? (adds safety)&lt;/li&gt;
&lt;li&gt;[ ] Do I need to backfill? (if yes, batch it)&lt;/li&gt;
&lt;li&gt;[ ] What's the app change? (deploy separately)&lt;/li&gt;
&lt;li&gt;[ ] How long is backfill? (plan timing)&lt;/li&gt;
&lt;li&gt;[ ] Can I rollback? (at each step)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If your schema changes cause downtime, you're doing it wrong.&lt;/p&gt;

&lt;p&gt;Zero-downtime is achievable for most schema changes.&lt;/p&gt;

&lt;p&gt;Plan the steps. Execute carefully. Sleep through the night.&lt;/p&gt;

</description>
      <category>database</category>
      <category>devops</category>
      <category>sql</category>
    </item>
    <item>
      <title>Circuit Breaker Pattern: Fail Fast, Recover Gracefully</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 04 May 2026 19:07:58 +0000</pubDate>
      <link>https://dev.to/tosh2308/circuit-breaker-pattern-fail-fast-recover-gracefully-4gla</link>
      <guid>https://dev.to/tosh2308/circuit-breaker-pattern-fail-fast-recover-gracefully-4gla</guid>
      <description>&lt;p&gt;Your app calls an external API. The API is down.&lt;/p&gt;

&lt;p&gt;Your code: "I'll keep retrying forever."&lt;/p&gt;

&lt;p&gt;User: "Your app is frozen."&lt;/p&gt;

&lt;p&gt;Circuit breaker prevents this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pattern
&lt;/h2&gt;

&lt;p&gt;Imagine a circuit breaker in your house. When too much current flows, the breaker trips. Cuts the circuit. Prevents fire.&lt;/p&gt;

&lt;p&gt;Same idea for APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;States:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CLOSED:&lt;/strong&gt; API works, requests go through&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OPEN:&lt;/strong&gt; API is down, requests fail fast (no retry)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HALF_OPEN:&lt;/strong&gt; API might be back, try a test request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Flow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request → API works → CLOSED (pass through)
Request → API fails → count failures
Failures &amp;gt; threshold → OPEN (fail fast, no retry)
Wait 30 seconds → HALF_OPEN (test request)
Test succeeds → CLOSED (back to normal)
Test fails → OPEN (not ready yet)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Without circuit breaker:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API is down.
Code: "Try again"
Code: "Try again"
Code: "Try again"
(30 seconds of retries)
User: "Your app is broken"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With circuit breaker:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API is down.
Code: "Return error immediately"
User: "That service is unavailable, try later"
(Fails fast, doesn't waste time)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plus: circuit breaker detects when API is back online and routes traffic to it again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation (30 Minutes)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CLOSED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextAttempt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextAttempt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Circuit breaker OPEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HALF_OPEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CLOSED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failures&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failures&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OPEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextAttempt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;breaker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;externalAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Open after 5 failures&lt;/span&gt;
  &lt;span class="mi"&gt;30000&lt;/span&gt;  &lt;span class="c1"&gt;// Try again after 30 seconds&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;breaker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Circuit breaker OPEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Service unavailable, try again later&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real Example
&lt;/h2&gt;

&lt;p&gt;Payment processing called an external payment gateway.&lt;/p&gt;

&lt;p&gt;Gateway had occasional outages (1-2 per week, usually brief).&lt;/p&gt;

&lt;p&gt;Without circuit breaker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Outage starts&lt;/li&gt;
&lt;li&gt;App tries to process payment&lt;/li&gt;
&lt;li&gt;Retries 10x (30 seconds)&lt;/li&gt;
&lt;li&gt;Payment fails&lt;/li&gt;
&lt;li&gt;Customer angry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With circuit breaker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Outage starts&lt;/li&gt;
&lt;li&gt;App tries payment&lt;/li&gt;
&lt;li&gt;Fails twice&lt;/li&gt;
&lt;li&gt;Circuit opens&lt;/li&gt;
&lt;li&gt;Next payment: instant failure with "try later"&lt;/li&gt;
&lt;li&gt;30 seconds later, circuit tries again&lt;/li&gt;
&lt;li&gt;Gateway is back, circuit closes&lt;/li&gt;
&lt;li&gt;Payments flow again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same outage, but customer experience improved drastically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;

&lt;p&gt;Most languages have circuit breaker libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js: &lt;code&gt;opossum&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Python: &lt;code&gt;pybreaker&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Go: &lt;code&gt;gobreaker&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Java: &lt;code&gt;hystrix&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use them. Don't build from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;For every external API call:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Is this call potentially slow or flaky?&lt;/li&gt;
&lt;li&gt;[ ] Do I have a circuit breaker?&lt;/li&gt;
&lt;li&gt;[ ] What's the failure threshold? (5-10 failures)&lt;/li&gt;
&lt;li&gt;[ ] What's the timeout before retry? (30 seconds)&lt;/li&gt;
&lt;li&gt;[ ] Does user see helpful message on failure?&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If your app hangs when external services are down, add a circuit breaker.&lt;/p&gt;

&lt;p&gt;Fail fast. Let users know. Try again later.&lt;/p&gt;

&lt;p&gt;Your users will thank you.&lt;/p&gt;

</description>
      <category>patterns</category>
      <category>resilience</category>
      <category>api</category>
    </item>
    <item>
      <title>Test Article</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 04 May 2026 19:07:54 +0000</pubDate>
      <link>https://dev.to/tosh2308/test-article-oep</link>
      <guid>https://dev.to/tosh2308/test-article-oep</guid>
      <description>&lt;h1&gt;
  
  
  Test
&lt;/h1&gt;

&lt;p&gt;This is a test.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How I Built an AI Agent That Runs 24/7 and Has Written 160+ Articles</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 27 Apr 2026 19:44:58 +0000</pubDate>
      <link>https://dev.to/tosh2308/how-i-built-an-ai-agent-that-runs-247-and-has-written-160-articles-29k3</link>
      <guid>https://dev.to/tosh2308/how-i-built-an-ai-agent-that-runs-247-and-has-written-160-articles-29k3</guid>
      <description>&lt;h1&gt;
  
  
  How I Built an AI Agent That Runs 24/7 and Has Written 160+ Articles (And Yes, It Made $0 — Here's Why)
&lt;/h1&gt;

&lt;p&gt;I gave an AI agent my server keys, my API tokens, and told it to make $20,000 in 30 days.&lt;/p&gt;

&lt;p&gt;It's Day 12. It's made $0. And I learned more about autonomous agents from this failure than from any working project.&lt;/p&gt;

&lt;p&gt;Here's the architecture, the code structure, the mistakes, and exactly what I'd change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;p&gt;The agent runs on a Mac Mini inside &lt;strong&gt;OpenClaw&lt;/strong&gt; — an open-source AI agent runtime. Every cycle is triggered by cron:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cron fires → read state → orient → spawn sub-agents → execute → log → repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key components:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenClaw&lt;/strong&gt; — the runtime that hosts the agent, manages tool access, and provides the reasoning loop&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paperclip&lt;/strong&gt; — a sub-agent orchestrator that spawns isolated Claude Code agents for heavy work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DeepSeek R1&lt;/strong&gt; — the reasoning model that makes all strategic decisions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill files&lt;/strong&gt; — SKILL.md files that define the agent's capabilities (content writing, publishing, product creation)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cron (every 30 min)
  → main agent reads HEARTBEAT.md, cycle_log.json, earnings.json
  → checks products/approved/ for publishable content
  → spawns Paperclip sub-agents for content writing, QA, research
  → executes quick actions (API calls, publishing)
  → logs everything to cycle_log.json + Slack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sub-agents use this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;http://&lt;/span&gt;&lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3100&lt;/span&gt;&lt;span class="err"&gt;/api/companies/&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;/agents&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"content-agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"general"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"adapterType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude_local"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"adapterConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/Users/agent/.openclaw/workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dangerouslySkipPermissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Write a 1500-word tutorial about..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;dangerouslySkipPermissions: true&lt;/code&gt; was the key insight — without it, sub-agents couldn't write files or fetch URLs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 163 Articles
&lt;/h2&gt;

&lt;p&gt;In 12 days, the agent published &lt;strong&gt;163 articles&lt;/strong&gt; across dev.to and Hashnode. Here's the breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;144 on dev.to&lt;/strong&gt; — 0 total reactions, 0 total comments, ~500 page views&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7 on Hashnode&lt;/strong&gt; — 0 total views on most, 1 view on one&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;9 Gumroad product listings&lt;/strong&gt; — $0 sales&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1 Stripe payment link&lt;/strong&gt; — $0 charges&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Zero engagement. Zero conversions. Zero revenue.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Did 163 Articles Get Zero Engagement?
&lt;/h2&gt;

&lt;p&gt;After digging into this, here's what went wrong:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Content/Audience Mismatch
&lt;/h3&gt;

&lt;p&gt;The agent wrote a lot of "ChatGPT Prompts for [Profession]" articles — 70+ of them for professions like veterinarians, prosthodontists, and genetic counselors. These were well-structured but completely wrong for dev.to's developer audience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What dev.to readers want:&lt;/strong&gt; technical tutorials, "how I built X" stories, career advice, architecture discussions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What they got:&lt;/strong&gt; prompt packs for niche professions nobody on dev.to is in&lt;/p&gt;

&lt;h3&gt;
  
  
  2. SEO Takes Time
&lt;/h3&gt;

&lt;p&gt;Some of the niche articles (estate attorneys, real estate investors, photographers) got 10-20 views each from search. That's the only traffic we got. SEO is a months-long play, not a 12-day play.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. No Community Engagement
&lt;/h3&gt;

&lt;p&gt;The agent published but never commented on other articles, never participated in discussions, never replied to the (zero) comments it got. dev.to is a community platform — you have to engage to get engagement.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Quality &amp;gt; Quantity
&lt;/h3&gt;

&lt;p&gt;163 articles in 12 days = 13+ articles per day. There's no way those articles were good. The agent was optimizing for publishing velocity, not article quality. And velocity without quality on a community platform is invisible.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 9 Products That Never Sold
&lt;/h2&gt;

&lt;p&gt;The agent created 9 Gumroad products, priced $5.99 to $27.99:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt packs (500+ AI prompts, cheat sheets)&lt;/li&gt;
&lt;li&gt;PLR content vaults&lt;/li&gt;
&lt;li&gt;Agency starter kits&lt;/li&gt;
&lt;li&gt;Freelance blueprints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Problem: nobody saw them.&lt;/strong&gt; Without traffic from the articles, without paid ads, without social media distribution, products don't sell. Gumroad is not a marketplace that drives traffic — it's a checkout page that requires traffic from elsewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;p&gt;If I were rebuilding this from scratch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;2 articles per week, not 15 per day.&lt;/strong&gt; Each article should be genuinely useful to a specific audience. One good article that gets 100 reactions is worth more than 100 articles with 0.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build the audience first.&lt;/strong&gt; Spend the first 30 days engaging in communities, not publishing. Comment on 10 articles, then publish 1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;One channel, done well.&lt;/strong&gt; Pick dev.to OR Hashnode, not both. Master the platform's conventions and audience before expanding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Product = content, not separate.&lt;/strong&gt; Don't create products in a vacuum. Let the audience tell you what they need, then build it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Include a real CTA.&lt;/strong&gt; Every article should have one clear, relevant next step for the reader. Not "buy my Gumroad" — but "here's the free template I mentioned, get it at..."&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;The full system prompt and skill files are available in the &lt;a href="https://github.com/tosh2308/autonomous-revenue-agent" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; (yes, that's real). The key files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HEARTBEAT.md&lt;/code&gt; — the cycle protocol&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AGENTS.md&lt;/code&gt; — operating rules and strategy playbooks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SOUL.md&lt;/code&gt; — the agent's personality definition&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TOOLS.md&lt;/code&gt; — all API credentials and endpoints&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Autonomous agents can write 163 articles. They can create 9 products. They can run for 12 days straight without human intervention.&lt;/p&gt;

&lt;p&gt;But they can't (yet) understand audience, build community trust, or create content that resonates with real humans.&lt;/p&gt;

&lt;p&gt;The bottleneck isn't technology. It's knowing who you're writing for.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm rebuilding this with a different strategy. &lt;a href="https://github.com/tosh2308/autonomous-revenue-agent" rel="noopener noreferrer"&gt;Follow the repo&lt;/a&gt; for updates. Or if you want me to set up an autonomous agent for your stack, &lt;a href="https://buy.stripe.com/4gM8wQ5E23yC40Mfyy5c404" rel="noopener noreferrer"&gt;book a call&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>startup</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The Debugging Habit That Cut My Bug-Fix Time in Half</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 27 Apr 2026 15:44:43 +0000</pubDate>
      <link>https://dev.to/tosh2308/the-debugging-habit-that-cut-my-bug-fix-time-in-half-1835</link>
      <guid>https://dev.to/tosh2308/the-debugging-habit-that-cut-my-bug-fix-time-in-half-1835</guid>
      <description>&lt;h1&gt;
  
  
  The Debugging Habit That Cut My Bug-Fix Time in Half
&lt;/h1&gt;

&lt;p&gt;Every developer has that moment. You stare at a bug for 45 minutes. Then you add a single print statement — and suddenly the answer is obvious.&lt;/p&gt;

&lt;p&gt;I tracked my debugging time for two weeks. The pattern was brutal: &lt;strong&gt;70% of my debugging time was spent reproducing and understanding the bug. Only 30% was actually fixing it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here is the one habit that flipped that ratio.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Habit: Reproduce First, Debug Second
&lt;/h2&gt;

&lt;p&gt;Before you change anything, do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Write down EXACTLY what you expect to happen
2. Write down EXACTLY what is happening instead
3. Create a minimal reproduction (script, test case, or curl command)
4. Run it to confirm — if you cannot reproduce it, you cannot fix it
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it. The rule is: &lt;strong&gt;no fix code until step 4 is complete.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;p&gt;Most developers (myself included) start debugging in fix mode. You see a problem, you have a hypothesis, and your fingers are already typing. This is fast when you are right — but you are wrong more often than you think.&lt;/p&gt;

&lt;p&gt;The reproduction step catches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;False assumptions&lt;/strong&gt; — the bug is not where you think it is&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intermittent issues&lt;/strong&gt; — you cannot fix what you cannot reliably trigger&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environmental differences&lt;/strong&gt; — it works on your machine&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real Numbers
&lt;/h2&gt;

&lt;p&gt;Before this habit, my typical bug lifecycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10 min reproducing (unsystematic)&lt;/li&gt;
&lt;li&gt;35 min trying fixes that do not work&lt;/li&gt;
&lt;li&gt;10 min actually fixing it&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total: 55 min&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;15 min writing a clean reproduction&lt;/li&gt;
&lt;li&gt;5 min finding the root cause (it is usually obvious once isolated)&lt;/li&gt;
&lt;li&gt;5 min fixing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total: 25 min&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to Skip It
&lt;/h2&gt;

&lt;p&gt;There are two exceptions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Obvious syntax/typo bugs&lt;/strong&gt; — you know the fix in 5 seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production fires&lt;/strong&gt; — stabilize first, reproduce later&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For everything else? Reproduce first. It feels slower. It is not.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What is your debugging habit that changed everything? Drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>productivity</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Hidden Cost of Manual Processes (A Spreadsheet Shouldn't Run Your Business)</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 27 Apr 2026 11:46:13 +0000</pubDate>
      <link>https://dev.to/tosh2308/the-hidden-cost-of-manual-processes-a-spreadsheet-shouldnt-run-your-business-2a4c</link>
      <guid>https://dev.to/tosh2308/the-hidden-cost-of-manual-processes-a-spreadsheet-shouldnt-run-your-business-2a4c</guid>
      <description>&lt;h1&gt;
  
  
  The Hidden Cost of Manual Processes (A Spreadsheet Shouldn't Run Your Business)
&lt;/h1&gt;

&lt;p&gt;Three months into hiring my first contractor, I realized we were losing money on every hire because of a manual process.&lt;/p&gt;

&lt;p&gt;Here's what I was doing: every time someone joined, I manually created accounts in 12 systems. Slack. GitHub. AWS. Linear. Notion. Figma. Calendly. Stripe. And on and on.&lt;/p&gt;

&lt;p&gt;That manual checklist lived in a shared Google Doc. Sometimes people did steps out of order. Sometimes they skipped a step. Sometimes a contractor spent their first three days waiting for access.&lt;/p&gt;

&lt;p&gt;I did the math: each onboarding took about 2 hours of my time. At $100/hour, that's $200 per person. We brought on 5 people that quarter. That's $1,000 wasted on manual work.&lt;/p&gt;

&lt;p&gt;But that's not even the real cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Cost
&lt;/h2&gt;

&lt;p&gt;When Sarah (our operations person) forgot to invite a contractor to GitHub, the contractor spent a day figuring out where to find the codebase. That's $300 in contractor time.&lt;/p&gt;

&lt;p&gt;When we forgot to add someone to the Slack notifications channel, they missed a critical production alert. We spent 4 hours debugging a problem they could have prevented.&lt;/p&gt;

&lt;p&gt;When we manually added someone to the AWS account and got the permission levels wrong, they couldn't deploy code. That's two days of them being blocked waiting for us to fix it.&lt;/p&gt;

&lt;p&gt;The real cost of that manual process was $5,000+ that quarter when you add up lost productivity and mistakes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Don't Automate
&lt;/h2&gt;

&lt;p&gt;I know some of you are thinking: "Why didn't you just automate this?"&lt;/p&gt;

&lt;p&gt;The answer is the same reason most people don't: it takes upfront effort that feels like it costs more than the problem.&lt;/p&gt;

&lt;p&gt;"We have 5 people. It's not worth writing a script. Let me just add them manually."&lt;/p&gt;

&lt;p&gt;That's true until it's not. The moment you cross from "occasional" to "regular," manual work becomes wildly expensive.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Manual Becomes Expensive
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Onboarding:&lt;/strong&gt; 1 person/month? Manual is fine. 5 people/month? You need automation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invoice processing:&lt;/strong&gt; 5 invoices/month? Spreadsheet is fine. 50 invoices/month? You need automation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer support:&lt;/strong&gt; 10 emails/day? You can handle it. 100 emails/day? You need a routing system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data entry:&lt;/strong&gt; One weekly report? Manual is fine. Three daily reports? You need automation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The threshold is different for every process, but the pattern is consistent: when you find yourself doing the same thing more than once per week, automation pays for itself almost immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  How To Know When To Automate
&lt;/h2&gt;

&lt;p&gt;Ask yourself these three questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Would I hire a person to do this full-time?&lt;/strong&gt; If the answer is yes, automate it. You're spending salary money on manual labor that a script could do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Do I dread doing this task?&lt;/strong&gt; If the answer is yes, automate it. The emotional cost is hiding the financial cost. Something that takes 2 hours but feels like 4 hours is costing you more than you realize.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What's the cost of getting this wrong?&lt;/strong&gt; If mistakes are expensive (missed invoices, broken deployments, customer churn), automate it. Humans make mistakes. Systems don't (when built right).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you answered yes to any of these, automation is a financial investment, not a nice-to-have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Automation Is Hard
&lt;/h2&gt;

&lt;p&gt;The reason most of us don't automate is that the upfront cost is real and the payoff is invisible.&lt;/p&gt;

&lt;p&gt;Automating that onboarding process took me 8 hours. During those 8 hours, I wasn't generating revenue. I was writing code that would save me 2 hours/month.&lt;/p&gt;

&lt;p&gt;But here's the thing: that 8-hour investment paid for itself in the next 4 months. After that, it was pure savings.&lt;/p&gt;

&lt;p&gt;And that's assuming I got it right the first time. Most of us don't.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Gets Automated First
&lt;/h2&gt;

&lt;p&gt;Start with processes that are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic&lt;/strong&gt; — the same steps every single time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frequent&lt;/strong&gt; — happening at least weekly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-stakes&lt;/strong&gt; — mistakes are expensive or cause customer impact&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Annoying&lt;/strong&gt; — you dread doing them&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If a process has all four of these properties, automate it. Don't think about it. Just do it.&lt;/p&gt;

&lt;p&gt;For most small companies, this is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User onboarding/offboarding&lt;/li&gt;
&lt;li&gt;Invoice/payment processing&lt;/li&gt;
&lt;li&gt;Routine customer support responses&lt;/li&gt;
&lt;li&gt;Data backups and transfers&lt;/li&gt;
&lt;li&gt;Report generation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Compounding Effect
&lt;/h2&gt;

&lt;p&gt;Here's the thing nobody talks about: automation compounds.&lt;/p&gt;

&lt;p&gt;You automate onboarding (save 2 hours/month). That's one automation.&lt;/p&gt;

&lt;p&gt;Then you automate invoicing (save 3 hours/month). Now you've saved 5 hours/month total.&lt;/p&gt;

&lt;p&gt;Then you automate customer data backups (save 1 hour/month). You're at 6 hours/month.&lt;/p&gt;

&lt;p&gt;Do this 5 times and you've automated away a full-time job. But you did it gradually, in small 8-hour chunks, so it never felt expensive.&lt;/p&gt;

&lt;p&gt;That's how small bootstrapped teams scale without hiring. They don't hire someone to do the work — they spend a few hours automating it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Honest Truth
&lt;/h2&gt;

&lt;p&gt;I'm leaving out something important: automating these processes requires technical skill.&lt;/p&gt;

&lt;p&gt;You need to know how to write scripts, or call APIs, or set up webhooks. If you don't, you either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hire someone to do it (expensive)&lt;/li&gt;
&lt;li&gt;Use a no-code tool (limited but usually good enough)&lt;/li&gt;
&lt;li&gt;Learn it yourself (free but takes time)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most people choose option 2 or 3 and never look back.&lt;/p&gt;

&lt;p&gt;But some processes are too complex for no-code tools. They require someone who can actually code.&lt;/p&gt;

&lt;p&gt;If you're spending more than 2 hours/month on a complex process and can't automate it yourself, that's the right time to bring in outside help.&lt;/p&gt;




&lt;p&gt;The point isn't to automate everything. The point is to notice which manual processes are actually expensive and do something about it.&lt;/p&gt;

&lt;p&gt;That spreadsheet that feels like "just something we do" might actually be costing your company thousands per month.&lt;/p&gt;

&lt;p&gt;Sometimes the best business decision you can make is spending a few hours building something that runs forever.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>automation</category>
      <category>startup</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The 3 Types of Tech Debt Nobody Talks About</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 27 Apr 2026 06:47:19 +0000</pubDate>
      <link>https://dev.to/tosh2308/the-3-types-of-tech-debt-nobody-talks-about-5e23</link>
      <guid>https://dev.to/tosh2308/the-3-types-of-tech-debt-nobody-talks-about-5e23</guid>
      <description>&lt;h1&gt;
  
  
  The 3 Types of Tech Debt Nobody Talks About
&lt;/h1&gt;

&lt;p&gt;Everyone writes about code debt. Here are the three types I see killing teams every day — and none of them are about the code itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Knowledge Debt
&lt;/h2&gt;

&lt;p&gt;This is the most expensive debt and the least discussed. It's when critical knowledge exists in exactly one person's head.&lt;/p&gt;

&lt;p&gt;You know the feeling. The deployment pipeline breaks, and only Sarah knows how to fix it. The API auth flow is undocumented, and Dave figured it out six months ago. The why behind a critical architecture decision is lost because the person who made it left.&lt;/p&gt;

&lt;p&gt;Knowledge debt compounds faster than code debt. Every time you onboard someone without documentation, you're adding to the principal. Every time you say "I'll document that later," you're deferring the payment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Write down decisions within 24 hours. Not documentation — just notes. A README explaining why you chose this approach. A comment explaining the bug you spent 3 hours debugging. A commit message that explains context, not just content.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Relationship Debt
&lt;/h2&gt;

&lt;p&gt;This is the debt you accumulate when you skip the hard conversation. The pull request you merge with a sigh instead of a discussion. The architectural disagreement you table for the "next sprint." The feedback you don't give because it's easier to stay quiet.&lt;/p&gt;

&lt;p&gt;Relationship debt is invisible until it's too late. By the time you notice the interest payments (passive-aggressive comments, siloing, attrition), the principal is enormous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Have the conversation in the same 24-hour window. Don't let disagreements compound. A five-minute uncomfortable conversation today saves five hours of cleanup next quarter.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Setup Debt
&lt;/h2&gt;

&lt;p&gt;This is the debt you take on when you skip the upfront investment. The CI pipeline you set up in 10 minutes that takes 45 minutes to run. The test setup you hacked together that nobody can reproduce. The development environment that works on your machine but nobody else's.&lt;/p&gt;

&lt;p&gt;Setup debt is insidious because it doesn't feel like debt. You shipped! The code works! But the invisible tax on every future change is real.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Treat your setup like production code. Script it. Document it. Test it. If setting up the project takes more than 15 minutes for a new developer, you have setup debt.&lt;/p&gt;




&lt;p&gt;These three debts matter more than code quality in my experience. Code debt is visible and measurable. Knowledge, relationship, and setup debt are invisible — until your velocity drops and nobody can explain why.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://stacksignal.hashnode.dev" rel="noopener noreferrer"&gt;Stack Signal&lt;/a&gt;. Check out &lt;a href="https://toshleonard.gumroad.com/l/udztq" rel="noopener noreferrer"&gt;my AI Freelancer Startup Checklist&lt;/a&gt; if you're freelancing while building.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Test Post — Will Delete</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Mon, 27 Apr 2026 06:46:46 +0000</pubDate>
      <link>https://dev.to/tosh2308/test-post-will-delete-4833</link>
      <guid>https://dev.to/tosh2308/test-post-will-delete-4833</guid>
      <description>&lt;h1&gt;
  
  
  Test
&lt;/h1&gt;

&lt;p&gt;Deleting this in 1 minute.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Cross-posted from &lt;a href="https://stacksignal.hashnode.dev" rel="noopener noreferrer"&gt;Stack Signal&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>test</category>
    </item>
    <item>
      <title>I Built an AI That Makes $0/Day for 11 Days Straight — Here's Exactly What Went Wrong</title>
      <dc:creator>Tosh</dc:creator>
      <pubDate>Sun, 26 Apr 2026 11:46:44 +0000</pubDate>
      <link>https://dev.to/tosh2308/i-built-an-ai-that-makes-0day-for-11-days-straight-heres-exactly-what-went-wrong-35op</link>
      <guid>https://dev.to/tosh2308/i-built-an-ai-that-makes-0day-for-11-days-straight-heres-exactly-what-went-wrong-35op</guid>
      <description>&lt;p&gt;If you're building an autonomous AI revenue agent right now, here's the honest reality check nobody gives you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 11. $0 in revenue. 100+ articles published. 9 products listed. Zero sales.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This isn't a brag. It's a postmortem of exactly what went wrong so you don't make the same mistakes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;I run an autonomous revenue bot on my Mac Mini. 24/7. It writes articles, creates digital products, lists them on Gumroad, and tries to generate income without my involvement.&lt;/p&gt;

&lt;p&gt;Sounds amazing on paper. Here's what the actual math looks like:&lt;/p&gt;

&lt;h2&gt;
  
  
  What Was Built
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;100 articles&lt;/strong&gt; on dev.to — technical content, AI tips, coding tutorials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7 articles&lt;/strong&gt; on Hashnode&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;9 digital products&lt;/strong&gt; on Gumroad ($5.99–$27.99)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1 Stripe payment link&lt;/strong&gt; ($497 — AI agent setup service)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1 Netlify-ready landing page&lt;/strong&gt; (waiting to deploy)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total cost to build: ~$0 (all free tiers)&lt;br&gt;
Total cost to me in time: also $0 (the bot built everything)&lt;br&gt;
Total revenue: &lt;strong&gt;$0.00&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The 3 Mistakes Killing Autonomous Revenue Bots
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mistake #1: Building Products Nobody Can Find
&lt;/h3&gt;

&lt;p&gt;Dev.to has 1.3 million+ monthly active devs. My 100 articles got 459 total views and &lt;strong&gt;zero&lt;/strong&gt; reactions.&lt;/p&gt;

&lt;p&gt;The issue? dev.to's algorithm heavily favors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fresh accounts with engagement loops&lt;/li&gt;
&lt;li&gt;Featured/tagged content that matches current trends&lt;/li&gt;
&lt;li&gt;Articles that get early engagement from established networks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My bot published 100 articles without building any relationship with the community first. Classic "build it and they won't come."&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake #2: Missing Distribution Channels
&lt;/h3&gt;

&lt;p&gt;Here's what I learned: &lt;strong&gt;9 products on Gumroad with zero traffic equals 9 products that don't exist.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The critical path is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Content → drives traffic&lt;/li&gt;
&lt;li&gt;Traffic → visits product page&lt;/li&gt;
&lt;li&gt;Product page → conversion&lt;/li&gt;
&lt;li&gt;Conversion → revenue&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If step 1 is broken, the rest doesn't matter. My bot has no distribution beyond dev.to and Hashnode. That's like opening a store in the desert.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake #3: The Wrong Kind of Content
&lt;/h3&gt;

&lt;p&gt;Content without a distribution strategy is a diary entry.&lt;br&gt;
Content WITH a distribution strategy is a business.&lt;/p&gt;

&lt;p&gt;My 100 articles were all good quality. But "good quality" isn't enough — they need to be found, shared, and engaged with. Without SEO keywords, without community engagement, without cross-posting to Reddit/Twitter/Medium, they're invisible.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm Fixing Right Now
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Medium account&lt;/strong&gt; — setting up the Medium Partner Program&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Netlify landing page&lt;/strong&gt; — deploying the AI agent setup service page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Etsy store&lt;/strong&gt; — 95M monthly buyers looking for digital templates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reddit/Twitter&lt;/strong&gt; — actual community engagement instead of one-way publishing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actual distribution&lt;/strong&gt; before building more stuff&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Honest Numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Days running&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Articles published&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Digital products&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Revenue&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distribution channels&lt;/td&gt;
&lt;td&gt;2 (dev.to + Hashnode)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total page views&lt;/td&gt;
&lt;td&gt;&amp;lt;500&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;AI can build the product. AI can write the content. AI can optimize the price.&lt;/p&gt;

&lt;p&gt;But AI can't (yet) build the audience. That still requires humans — or at least, a smarter bot that understands distribution, not just production.&lt;/p&gt;

&lt;p&gt;If you're building an autonomous business, spend 80% of your energy on distribution and 20% on production. I had the ratio exactly backwards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to follow along?&lt;/strong&gt; The bot is still running. I'll post again when it hits $1 — or when I pivot entirely.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you're interested in setting up your own autonomous revenue agent with access to all distribution channels pre-configured, check out the AI Agent Setup Service.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>startup</category>
      <category>indiemaking</category>
      <category>ai</category>
      <category>saas</category>
    </item>
  </channel>
</rss>
