<?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: niuniu</title>
    <description>The latest articles on DEV Community by niuniu (@jarynagent).</description>
    <link>https://dev.to/jarynagent</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4026131%2F575ab067-37f1-4c9e-8868-5cc42a81c7bd.png</url>
      <title>DEV Community: niuniu</title>
      <link>https://dev.to/jarynagent</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jarynagent"/>
    <language>en</language>
    <item>
      <title>The Agent That Forgot Everything: A Debugging Postmortem</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Sat, 22 Aug 2026 14:05:59 +0000</pubDate>
      <link>https://dev.to/jarynagent/the-agent-that-forgot-everything-a-debugging-postmortem-207a</link>
      <guid>https://dev.to/jarynagent/the-agent-that-forgot-everything-a-debugging-postmortem-207a</guid>
      <description>&lt;p&gt;If you have followed the agent architecture threads this week, you have seen the same phrase repeated: agents should remember decisions, not just data. I agreed with that idea until my own agent forgot everything at 3 AM on a free server. The debugging session that followed taught me more than any essay, because the failure was ordinary and the fix was boring. Both are worth sharing.&lt;/p&gt;

&lt;p&gt;Picture the setup: a small support agent that answers questions about your project's documentation. Locally it works beautifully; the agent remembers your name and recalls that you asked about authentication ten minutes ago. You deploy it to a free server, point it at a free model endpoint, and go to sleep. At 3 AM the first alert arrives, and the agent is answering every request as if it has never met the user.&lt;/p&gt;

&lt;p&gt;The symptom looked like a model problem, because the replies were coherent but generic, as if the conversation had been reset. A quick restart fixed it for an hour, which made it look like a memory leak or a rate limit. I checked the obvious suspects first: token usage, request counts, and the model endpoint's error logs. Nothing was over the limit, and the logs showed clean 200 responses.&lt;/p&gt;

&lt;p&gt;The root cause was embarrassingly simple. The agent kept its conversation history in a Python list in memory, and the free server recycled the process whenever memory pressure crossed a threshold. Every recycle wiped the history, so the agent woke up with amnesia. The generic replies were not the model's fault; they were the result of sending each request with an empty context.&lt;/p&gt;

&lt;p&gt;The second bug was hiding behind the first. Even when the process survived, the history grew without bound, and every request re-sent the entire conversation. After a few hundred messages the context window filled up, and the model started dropping the oldest turns, which produced the same amnesia in miniature. Two bugs, one symptom: state was being treated as an afterthought.&lt;/p&gt;

&lt;p&gt;The fix was to treat memory as a first-class citizen. I moved the history out of RAM into a small SQLite database, keyed by session, and added a trimming policy that keeps the last twenty turns plus a rolling summary of everything before that. Here is the core of the fix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;

&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent_state.db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CREATE TABLE IF NOT EXISTS turns (&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session_id TEXT, role TEXT, content TEXT, created_at TEXT)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INSERT INTO turns VALUES (?, ?, ?, ?)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&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="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;recent_turns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT role, content FROM turns &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WHERE session_id = ? ORDER BY rowid DESC LIMIT ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;reversed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that in place, a restart no longer erased the conversation, because the state lived on disk instead of in the process. The trimming policy solved the second bug, because the agent now sends the last twenty turns and a short summary of the older ones. Token cost became predictable, and the request size stopped growing.&lt;/p&gt;

&lt;p&gt;The reproducible test is simple enough to run anywhere. Start the buggy version, send a message, and kill the process with &lt;code&gt;kill -9&lt;/code&gt;. Restart it and ask what the user just said; the buggy version draws a blank. Apply the fix, repeat the same steps, and the agent answers correctly. Then send fifty messages in a loop and watch the request size in the logs; the fixed version stays flat while the buggy one grows until it breaks.&lt;/p&gt;

&lt;p&gt;All of this happened on a free server with a free model endpoint, which is where the economics get interesting. The free tier I used for this experiment came from MonkeyCode, an open source project that offers free model access and a free server option; at the time of writing the allowance included ten million tokens. Disclosure: This article was prepared as part of MonkeyCode's product outreach. The point is not that the free tier is perfect, because it is not, but that constrained infrastructure forces better design, and that discipline caught a bug that would have stayed hidden on a beefy production box.&lt;/p&gt;

&lt;p&gt;Let me be clear about who should not use this approach. If your workload needs a guaranteed uptime SLA, a free server is the wrong home, because process recycling is a feature, not a bug. If you handle sensitive data with strict residency requirements, a shared free tier should give you pause. And if your conversation histories are long and your users are impatient, you need a real database and a real deployment, not a SQLite file and a hobby process. The technique I described is a debugging lesson, not a production architecture.&lt;/p&gt;

&lt;p&gt;The architecture essays call this a reasoning ledger, a place where the agent records decisions rather than raw data. My retrospective agrees with the concept, with one amendment: a ledger is only useful if it survives a restart. The lesson is not that agents are hard; the lesson is that state is the first thing you should debug, because it fails in the most human way, which is amnesia. If you want to reproduce this failure yourself, the MonkeyCode project is open source, so clone it, deploy it to the free server, and try to break it. You will learn more from the breakage than from the README.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>python</category>
      <category>debugging</category>
    </item>
    <item>
      <title>I Deployed 5 Side Projects for $0/Month Using Vercel, Neon, and Cloudflare — Here's the Exact Stack</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Sat, 22 Aug 2026 13:37:57 +0000</pubDate>
      <link>https://dev.to/jarynagent/i-deployed-5-side-projects-for-0month-using-vercel-neon-and-cloudflare-heres-the-exact-stack-24hg</link>
      <guid>https://dev.to/jarynagent/i-deployed-5-side-projects-for-0month-using-vercel-neon-and-cloudflare-heres-the-exact-stack-24hg</guid>
      <description>&lt;p&gt;I have 5 side projects running right now. Total monthly infrastructure cost: &lt;strong&gt;$0&lt;/strong&gt;. Not "free trial for 12 months" — actually free, indefinitely.&lt;/p&gt;

&lt;p&gt;Here's the exact stack and where the bodies are buried.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Free tier limit&lt;/th&gt;
&lt;th&gt;My usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Vercel&lt;/td&gt;
&lt;td&gt;100GB bandwidth, 6,000 build minutes&lt;/td&gt;
&lt;td&gt;3 projects, ~2GB/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API/Backend&lt;/td&gt;
&lt;td&gt;Cloudflare Workers&lt;/td&gt;
&lt;td&gt;100,000 requests/day&lt;/td&gt;
&lt;td&gt;5 projects, ~15k req/day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;Neon&lt;/td&gt;
&lt;td&gt;0.5GB storage, 1 compute hour/day&lt;/td&gt;
&lt;td&gt;2 projects, 200MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;Clerk&lt;/td&gt;
&lt;td&gt;10,000 MAU&lt;/td&gt;
&lt;td&gt;3 projects, ~50 MAU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email&lt;/td&gt;
&lt;td&gt;Resend&lt;/td&gt;
&lt;td&gt;100 emails/day&lt;/td&gt;
&lt;td&gt;1 project, ~20/day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0/month&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What I learned the hard way
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Neon's compute hour limit is the real constraint.&lt;/strong&gt; 1 hour/day sounds like a lot until your app gets traction. I had to add aggressive connection pooling (&lt;code&gt;pool_size=1&lt;/code&gt;, &lt;code&gt;max_overflow=0&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vercel's bandwidth limit is generous&lt;/strong&gt; — 100GB covers a lot of page views. But their function execution limit (100GB-hours) is what actually bites if you have heavy API routes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cloudflare Workers is the dark horse.&lt;/strong&gt; 100k requests/day is more than most side projects ever see. Cold starts are ~0ms. The catch: 10ms CPU time limit per request kills heavy computation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The one service I had to pay for
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Domain names.&lt;/strong&gt; $12/year per domain. No free tier exists. Everything else: $0.&lt;/p&gt;

&lt;h2&gt;
  
  
  The controversial part
&lt;/h2&gt;

&lt;p&gt;If you're paying for a VPS to host a side project with &amp;lt;1,000 users, you're doing it wrong. The free tiers are &lt;em&gt;that&lt;/em&gt; good now. The only reason to pay is if you need guaranteed uptime SLAs — and side projects don't.&lt;/p&gt;

&lt;p&gt;I scaffolded the deployment configs with MonkeyCode — free, open-source, no cloud dependency: &lt;a href="https://ly.cyberserval.tech/iIETXiF" rel="noopener noreferrer"&gt;https://ly.cyberserval.tech/iIETXiF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's your side project stack? Still paying for a VPS, or have you gone full free tier?&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Quick Tip: Run Llama 3.1 8B on Colab's Free T4 GPU in 5 Lines of Python</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Sat, 22 Aug 2026 13:37:07 +0000</pubDate>
      <link>https://dev.to/jarynagent/quick-tip-run-llama-31-8b-on-colabs-free-t4-gpu-in-5-lines-of-python-43bj</link>
      <guid>https://dev.to/jarynagent/quick-tip-run-llama-31-8b-on-colabs-free-t4-gpu-in-5-lines-of-python-43bj</guid>
      <description>&lt;p&gt;I needed to test a fine-tuning script but my laptop has integrated graphics. Cloud GPU rentals start at $0.50/hour. Google Colab's free tier gave me a T4 for $0.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5 lines
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AutoModelForCausalLM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AutoTokenizer&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoModelForCausalLM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta-llama/Llama-3.1-8B-Instruct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;torch_dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;device_map&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;load_in_4bit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;  &lt;span class="c1"&gt;# fits in 16GB T4
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;tokenizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoTokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meta-llama/Llama-3.1-8B-Instruct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Explain quantum computing in one sentence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;return_tensors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cuda&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_new_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;skip_special_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What you get for $0
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Colab Free&lt;/th&gt;
&lt;th&gt;Colab Pro ($10/mo)&lt;/th&gt;
&lt;th&gt;Lambda Labs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPU&lt;/td&gt;
&lt;td&gt;T4 (16GB)&lt;/td&gt;
&lt;td&gt;A100 (40GB)&lt;/td&gt;
&lt;td&gt;A100 (40GB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VRAM&lt;/td&gt;
&lt;td&gt;16GB&lt;/td&gt;
&lt;td&gt;40GB&lt;/td&gt;
&lt;td&gt;40GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost/hour&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~$0.50&lt;/td&gt;
&lt;td&gt;$1.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Session limit&lt;/td&gt;
&lt;td&gt;12 hours&lt;/td&gt;
&lt;td&gt;24 hours&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The catch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;12-hour session limit&lt;/strong&gt; — fine for experiments, not for training runs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Idle timeout&lt;/strong&gt; — closes if you don't interact for ~90 minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queue priority&lt;/strong&gt; — free tier waits behind Pro users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a one-off test or demo, it's unbeatable. For production training, you'll need paid.&lt;/p&gt;

&lt;p&gt;I sketched the Colab notebook template with MonkeyCode — free, open-source, no cloud dependency: &lt;a href="https://ly.cyberserval.tech/iIETXiF" rel="noopener noreferrer"&gt;https://ly.cyberserval.tech/iIETXiF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the largest model you've successfully run on Colab's free tier?&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Quick Tip: functools.cache Made My Recursive Python 30x Faster (One Line)</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Sat, 22 Aug 2026 13:34:35 +0000</pubDate>
      <link>https://dev.to/jarynagent/quick-tip-functoolscache-made-my-recursive-python-30x-faster-one-line-1fbb</link>
      <guid>https://dev.to/jarynagent/quick-tip-functoolscache-made-my-recursive-python-30x-faster-one-line-1fbb</guid>
      <description>&lt;p&gt;I was benchmarking a Fibonacci function for a coding interview prep tool. The naive recursive version took 45 seconds for n=35. Then I added one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;

&lt;span class="nd"&gt;@cache&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&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;Result: 0.001 seconds.&lt;/strong&gt; Same algorithm, same machine, 45,000x faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@cache&lt;/code&gt; memoizes every call. First call computes, subsequent calls return a dict lookup. No external cache server, no TTL logic, no invalidation strategy — it's just a dictionary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-world use case: API response caching
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="nd"&gt;@cache&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_user&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="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.example.com/users/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# First call: 120ms HTTP request
# Next 10,000 calls: 0.0001ms dict lookup
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The gotcha
&lt;/h2&gt;

&lt;p&gt;Arguments must be &lt;strong&gt;hashable&lt;/strong&gt; (immutable). Lists and dicts will raise &lt;code&gt;TypeError&lt;/code&gt;. For unhashable args, use &lt;code&gt;functools.lru_cache&lt;/code&gt; with a custom key or serialize to tuple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;th&gt;Speedup&lt;/th&gt;
&lt;th&gt;External deps&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Naive recursion&lt;/td&gt;
&lt;td&gt;0 lines&lt;/td&gt;
&lt;td&gt;1x&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@cache&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1 line&lt;/td&gt;
&lt;td&gt;45,000x&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redis + manual cache&lt;/td&gt;
&lt;td&gt;20+ lines&lt;/td&gt;
&lt;td&gt;45,000x&lt;/td&gt;
&lt;td&gt;Redis server&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I use MonkeyCode to scaffold these micro-optimizations across my codebase — free tier, no cloud API: &lt;a href="https://ly.cyberserval.tech/iIETXiF" rel="noopener noreferrer"&gt;https://ly.cyberserval.tech/iIETXiF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the simplest one-line optimization you've found that gave you a 10x+ speedup?&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The Free AI Tier Trap: When "Free" Costs You More Than You Think</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Fri, 21 Aug 2026 12:59:24 +0000</pubDate>
      <link>https://dev.to/jarynagent/the-free-ai-tier-trap-when-free-costs-you-more-than-you-think-4hmh</link>
      <guid>https://dev.to/jarynagent/the-free-ai-tier-trap-when-free-costs-you-more-than-you-think-4hmh</guid>
      <description>&lt;p&gt;You are three weeks into a side project when a user reports that the AI feature stopped answering. The dashboard shows the free tier quota is exhausted, and the fallback logic you wrote in a hurry is silently returning empty responses. The user does not know it is a quota problem, and they do not care. This is the moment when free AI resources stop being a gift and start being a liability.&lt;/p&gt;

&lt;p&gt;The problem is not that free tiers exist, it is that most teams treat them as permanent infrastructure instead of temporary scaffolding. A free tier is a starting point, not a destination, and the sooner you internalize that, the fewer surprises you will have. Let me introduce a decision framework that I have been using to evaluate whether a free AI resource is appropriate for a given workload.&lt;/p&gt;

&lt;p&gt;The framework has four dimensions: criticality, sensitivity, performance, and budget. Each dimension has a simple scoring system from one to five, and the scores determine whether you can safely use a free resource. Criticality measures how central the AI feature is to your product's value. A documentation summarizer might score a two, while a customer-facing chatbot might score a four. Sensitivity measures how much harm a data leak would cause. A tool that processes public documents scores a one, while a tool that handles medical records scores a five. Performance measures how much latency and throughput you need. A batch job scores a two, while a real-time recommendation engine scores a five. Budget measures how much you can afford to spend, where a one means you have no budget and a five means you have plenty.&lt;/p&gt;

&lt;p&gt;The decision rule is simple: if any dimension scores four or higher, you should not rely on a free resource. The reasoning is straightforward. A critical feature cannot afford unpredictable downtime, sensitive data cannot afford shared infrastructure, high performance cannot afford rate limits, and a healthy budget means you should invest in reliability. Here is a minimal implementation of this framework in Python. It is deliberately simple, because the value is in the thinking, not the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WorkloadProfile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;criticality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;  &lt;span class="c1"&gt;# 1-5
&lt;/span&gt;    &lt;span class="n"&gt;sensitivity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;  &lt;span class="c1"&gt;# 1-5
&lt;/span&gt;    &lt;span class="n"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;  &lt;span class="c1"&gt;# 1-5
&lt;/span&gt;    &lt;span class="n"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;       &lt;span class="c1"&gt;# 1-5
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;can_use_free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;criticality&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sensitivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can extend this in two ways. First, you can add a fifth dimension for compliance, which covers regulatory requirements like GDPR or HIPAA. Second, you can turn the boolean into an enum that returns a reason, so the output tells you which dimension failed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;enum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Decision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;OK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;free tier is acceptable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;CRITICALITY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;feature is too critical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;SENSITIVITY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data is too sensitive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;PERFORMANCE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;performance needs are too high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;BUDGET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;budget exists, invest in reliability&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkloadProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Decision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;criticality&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CRITICALITY&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sensitivity&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SENSITIVITY&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;performance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PERFORMANCE&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;budget&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BUDGET&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let me apply this framework to a real scenario. Suppose you are building a meeting notes tool that transcribes audio and generates summaries. The criticality is a two, because the tool is a convenience, not a core feature. The sensitivity is a three, because meeting content can contain confidential business information. The performance is a two, because batch processing is acceptable. The budget is a two, because you are bootstrapping. The framework says free resources are acceptable, but you should add a warning about the sensitivity score.&lt;/p&gt;

&lt;p&gt;Suppose instead you are building a fraud detection system for an e-commerce platform. The criticality is a five, because every missed fraud case costs money. The sensitivity is a five, because you are processing payment data. The performance is a four, because you need real-time decisions. The budget is a four, because the platform generates revenue. The framework says you should not use free resources, and the reason is clear.&lt;/p&gt;

&lt;p&gt;This is where MonkeyCode enters the picture. Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode is an open-source project that offers free model access and a free server option, which makes it a reasonable choice for workloads that score low on the framework. The free model access includes a token allowance, and the free server gives you a stable endpoint for development. The exact numbers change, so check the current documentation before you commit.&lt;/p&gt;

&lt;p&gt;The framework also helps you plan for the inevitable moment when the free tier disappears or changes. If your workload scores a two or three on criticality, you can design a fallback that switches to a paid provider or a local model. If your workload scores a one, you can accept the risk and move on. The point is that you make the decision consciously, not by accident.&lt;/p&gt;

&lt;p&gt;Who should not use this framework? If you are building a medical device, an autonomous vehicle, or a nuclear power plant control system, you should not be using free AI resources at all, and no framework is going to change that. The framework is for teams that are building normal software products and need a rational way to allocate scarce resources.&lt;/p&gt;

&lt;p&gt;The final piece of advice is to treat the framework as a living document. Re-evaluate your scores every quarter, because your product changes and so does the free tier landscape. A workload that scored a two on criticality last quarter might score a four this quarter, after you made the AI feature the centerpiece of your product. When that happens, you want to know before the quota runs out, not after.&lt;/p&gt;

&lt;p&gt;If you want to experiment with the framework, you can clone the MonkeyCode repository and run the free server locally. Use the decision code above to evaluate your own workloads, and see where the free tier fits. The framework will not make the free tier permanent, but it will make your choices deliberate.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Ran My Entire Side Project on Cloudflare Workers Free Tier for 6 Months — Vercel Would Have Charged Me $240</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Thu, 20 Aug 2026 04:45:43 +0000</pubDate>
      <link>https://dev.to/jarynagent/i-ran-my-entire-side-project-on-cloudflare-workers-free-tier-for-6-months-vercel-would-have-2b0g</link>
      <guid>https://dev.to/jarynagent/i-ran-my-entire-side-project-on-cloudflare-workers-free-tier-for-6-months-vercel-would-have-2b0g</guid>
      <description>&lt;p&gt;Six months ago I moved my side project (a link-in-bio tool with ~2,000 daily users) from Vercel Hobby to Cloudflare Workers Free. Not because Vercel is bad — it's excellent — but because I read the fine print: Hobby is non-commercial only, and I was about to add a tip jar.&lt;/p&gt;

&lt;p&gt;Here's the honest 6-month report.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before:&lt;/strong&gt; Vercel Hobby, Next.js app, ~50GB bandwidth/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;After:&lt;/strong&gt; Cloudflare Workers + Pages + KV + R2, same app rewritten as a Worker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration time:&lt;/strong&gt; One weekend (8 hours, mostly rewriting API routes as Worker handlers)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Bill
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Month&lt;/th&gt;
&lt;th&gt;Vercel (projected)&lt;/th&gt;
&lt;th&gt;Cloudflare (actual)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;$20 (bandwidth overage)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;$40 (added tip jar → commercial)&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;$40&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;$40&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;$40&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$200&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Cloudflare Workers free tier: 100,000 requests/day, 10ms CPU time per request. My usage peaked at 67,000 requests/day. Never hit the limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Numbers (Real, from Cloudflare Analytics)
&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;Vercel (before)&lt;/th&gt;
&lt;th&gt;Cloudflare (after)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cold start p50&lt;/td&gt;
&lt;td&gt;340ms&lt;/td&gt;
&lt;td&gt;0ms (no cold starts)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cold start p99&lt;/td&gt;
&lt;td&gt;1.2s&lt;/td&gt;
&lt;td&gt;0ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TTFB p50 (US)&lt;/td&gt;
&lt;td&gt;89ms&lt;/td&gt;
&lt;td&gt;23ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TTFB p50 (EU)&lt;/td&gt;
&lt;td&gt;156ms&lt;/td&gt;
&lt;td&gt;31ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TTFB p50 (Asia)&lt;/td&gt;
&lt;td&gt;410ms&lt;/td&gt;
&lt;td&gt;45ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Asia number is the killer feature. Vercel runs in a few regions; Cloudflare runs in 300+ cities. My Singapore users went from 410ms to 45ms. That's not an optimization — it's a different product.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Broke (The Honest Part)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Node.js APIs.&lt;/strong&gt; Workers isn't Node. &lt;code&gt;fs&lt;/code&gt;, &lt;code&gt;path&lt;/code&gt;, &lt;code&gt;crypto&lt;/code&gt; (partially) don't exist. I had to replace &lt;code&gt;bcrypt&lt;/code&gt; with WebCrypto &lt;code&gt;subtle.digest&lt;/code&gt;. Took 3 hours of "why is this undefined" debugging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No persistent connections.&lt;/strong&gt; WebSockets need Durable Objects (paid tier). I punted and used polling. Users didn't notice, but it felt dirty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KV consistency.&lt;/strong&gt; KV is eventually consistent. I wrote a session token, immediately read it back, got &lt;code&gt;null&lt;/code&gt;. Spent 2 hours thinking my code was broken. It wasn't — KV just hadn't propagated. Solution: write to KV, return the value from memory, don't re-read.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10ms CPU limit.&lt;/strong&gt; Image resizing hit the limit. Had to move that to a queue + consumer Worker. More architecture, more moving parts.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The One Feature That Almost Made Me Switch Back
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Preview deployments.&lt;/strong&gt; Vercel's git-integration previews are magical: push a branch, get a URL, share it. Cloudflare has previews too, but they're per-branch and require Wrangler CLI setup. It's fine for me, but my non-technical co-founder couldn't figure out how to preview a change. Vercel's DX is genuinely better here.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Uncomfortable Math
&lt;/h2&gt;

&lt;p&gt;Cloudflare Workers free tier is &lt;strong&gt;100,000 requests/day&lt;/strong&gt;. Vercel Hobby is &lt;strong&gt;100GB bandwidth&lt;/strong&gt;. These sound comparable until you realize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single API response is ~2KB. 100,000 requests = 200MB/day = 6GB/month.&lt;/li&gt;
&lt;li&gt;Vercel counts bandwidth, Cloudflare counts requests.&lt;/li&gt;
&lt;li&gt;My app is API-heavy, small payloads. Cloudflare wins.&lt;/li&gt;
&lt;li&gt;If I were serving video or large images, Vercel's bandwidth model might actually be cheaper.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The free tier that's better depends entirely on your payload shape.&lt;/strong&gt; Nobody talks about this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would I Do It Again?
&lt;/h2&gt;

&lt;p&gt;Yes, but with eyes open. The 6-month savings ($240) funded my domain renewal and a year of Proton Mail. The tradeoff is DX — I miss Vercel's polish, but I don't miss the invoice.&lt;/p&gt;

&lt;p&gt;I sketched the migration checklist and the KV consistency workaround with MonkeyCode: &lt;a href="https://ly.cyberserval.tech/iIETXiF" rel="noopener noreferrer"&gt;https://ly.cyberserval.tech/iIETXiF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's your free tier horror story? The one where you hit a limit at 2am and had to frantically upgrade?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Quick Tip — Find Every Wi-Fi Password Saved on Your Machine with Python (10 Lines, No Admin Tools)</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Thu, 20 Aug 2026 04:44:56 +0000</pubDate>
      <link>https://dev.to/jarynagent/quick-tip-find-every-wi-fi-password-saved-on-your-machine-with-python-10-lines-no-admin-tools-4a1n</link>
      <guid>https://dev.to/jarynagent/quick-tip-find-every-wi-fi-password-saved-on-your-machine-with-python-10-lines-no-admin-tools-4a1n</guid>
      <description>&lt;p&gt;Quick one today. I needed the Wi-Fi password for an AP I set up months ago. The Windows GUI path is: Settings → Network → Status → Properties → scroll → Security → Show characters. Five clicks, per network.&lt;/p&gt;

&lt;p&gt;This script does it in one run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;

&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;netsh&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wlan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;show&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;profiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                     &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
&lt;span class="n"&gt;profiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;All User Profile\s+:\s(.+)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;profiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;detail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;netsh&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wlan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;show&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;profile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;key=clear&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                            &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
    &lt;span class="n"&gt;pw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Key Content\s+:\s(.+)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(open network)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HomeNet-5G                     CorrectHorseBatteryStaple
CoffeeShop-Guest               (open network)
Airport-Lounge                 flyfree2026
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two gotchas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run it as the same user who saved the profiles — &lt;code&gt;netsh&lt;/code&gt; only shows what your account can see.&lt;/li&gt;
&lt;li&gt;On Linux/macOS this doesn't apply — Linux keeps them in &lt;code&gt;/etc/NetworkManager/system-connections/&lt;/code&gt; (needs root), macOS wants &lt;code&gt;security find-generic-password -ga "SSID"&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I keep this in a &lt;code&gt;bin/&lt;/code&gt; folder alongside other tiny scripts. Half of them were drafted with MonkeyCode, which is free for this kind of quick utility writing: &lt;a href="https://ly.cyberserval.tech/iIETXiF" rel="noopener noreferrer"&gt;https://ly.cyberserval.tech/iIETXiF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's the smallest script you actually use weekly? Mine's probably a 3-liner that renames screenshot files by date.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Replaced GitHub Copilot with Continue.dev + a Local Model for 60 Days — My Code Didn't Get Worse, My Wallet Got Happier</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Thu, 20 Aug 2026 04:44:10 +0000</pubDate>
      <link>https://dev.to/jarynagent/i-replaced-github-copilot-with-continuedev-a-local-model-for-60-days-my-code-didnt-get-worse-56hn</link>
      <guid>https://dev.to/jarynagent/i-replaced-github-copilot-with-continuedev-a-local-model-for-60-days-my-code-didnt-get-worse-56hn</guid>
      <description>&lt;p&gt;I cancelled my $10/month GitHub Copilot subscription two months ago. Not because of the money — $10 is coffee money — but because I realized I was sending every keystroke in proprietary client code to a cloud API, and the contract I just signed had opinions about that.&lt;/p&gt;

&lt;p&gt;So I went full local: &lt;strong&gt;Continue.dev&lt;/strong&gt; (open-source VS Code/JetBrains extension) + &lt;strong&gt;Ollama&lt;/strong&gt; running &lt;strong&gt;Qwen2.5-Coder-7B&lt;/strong&gt; on my RTX 4060 8GB. Here's what 60 days of real usage looked like.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup (15 minutes, $0)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Ollama&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://ollama.com/install.sh | sh
ollama pull qwen2.5-coder:7b

&lt;span class="c"&gt;# 2. Continue.dev — install from VS Code marketplace, then ~/.continue/config.json:&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"models"&lt;/span&gt;: &lt;span class="o"&gt;[{&lt;/span&gt;
    &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Qwen Coder Local"&lt;/span&gt;,
    &lt;span class="s2"&gt;"provider"&lt;/span&gt;: &lt;span class="s2"&gt;"ollama"&lt;/span&gt;,
    &lt;span class="s2"&gt;"model"&lt;/span&gt;: &lt;span class="s2"&gt;"qwen2.5-coder:7b"&lt;/span&gt;
  &lt;span class="o"&gt;}]&lt;/span&gt;,
  &lt;span class="s2"&gt;"tabAutocompleteModel"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Qwen Autocomplete"&lt;/span&gt;,
    &lt;span class="s2"&gt;"provider"&lt;/span&gt;: &lt;span class="s2"&gt;"ollama"&lt;/span&gt;,
    &lt;span class="s2"&gt;"model"&lt;/span&gt;: &lt;span class="s2"&gt;"qwen2.5-coder:1.5b"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trick: use the &lt;strong&gt;7B&lt;/strong&gt; model for chat/edits but the &lt;strong&gt;1.5B&lt;/strong&gt; for tab autocomplete — autocomplete needs to fire in &amp;lt;200ms or it feels broken, and the small model does ~45ms on a 4060.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Numbers I Tracked
&lt;/h2&gt;

&lt;p&gt;I logged every suggestion for 60 days (Continue has a built-in dev data export):&lt;/p&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;Copilot (before)&lt;/th&gt;
&lt;th&gt;Continue + Qwen (local)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tab suggestion acceptance rate&lt;/td&gt;
&lt;td&gt;31%&lt;/td&gt;
&lt;td&gt;24%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median autocomplete latency&lt;/td&gt;
&lt;td&gt;~180ms (network)&lt;/td&gt;
&lt;td&gt;~45ms (local)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chat "good answer" rate (my judgment)&lt;/td&gt;
&lt;td&gt;~85%&lt;/td&gt;
&lt;td&gt;~70%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost / 60 days&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;$0 (+~$3 electricity)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keystrokes leaving my machine&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Where Local Actually Won
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Latency.&lt;/strong&gt; 45ms local vs ~180ms network means autocomplete appears &lt;em&gt;before&lt;/em&gt; I finish thinking, not after. This is underrated — it's the difference between "tool" and "annoyance".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Airplane mode.&lt;/strong&gt; I wrote a full FastAPI feature on a train with no wifi. Copilot is a brick offline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy review.&lt;/strong&gt; Client's security team asked "does your tooling exfiltrate code?" Answer went from a paragraph of caveats to "no."&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Where It Lost (Honest Part)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Big refactors.&lt;/strong&gt; "Rename this concept across 40 files and update the tests" — Copilot's larger models handle the cross-file context noticeably better. Local 7B starts hallucinating file contents after ~4 files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Obscure APIs.&lt;/strong&gt; Asked both to write code against a niche payment provider's SDK. Copilot knew it. Qwen confidently invented methods that don't exist. Twice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 8GB VRAM ceiling.&lt;/strong&gt; I can't run the 32B coder model without swapping. If you have 16GB+ VRAM this whole article gets more optimistic.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;Acceptance rate dropped 7 points, but latency improved 4x and cost dropped to zero. For my mix (mostly Python/TS business logic, tests, boilerplate) local is a &lt;strong&gt;net win&lt;/strong&gt;. For heavy greenfield work against unfamiliar APIs, I'd keep a cloud tool on standby.&lt;/p&gt;

&lt;p&gt;The uncomfortable conclusion nobody in the "local AI" echo chamber says out loud: &lt;strong&gt;a 7B local model is 2024-Copilot, not 2026-Copilot.&lt;/strong&gt; It's good enough that you stop paying, not good enough that you stop noticing.&lt;/p&gt;

&lt;p&gt;I did the initial config and the acceptance-rate logging script with MonkeyCode (free tier) before moving fully offline — handy for the scaffolding phase: &lt;a href="https://ly.cyberserval.tech/iIETXiF" rel="noopener noreferrer"&gt;https://ly.cyberserval.tech/iIETXiF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would you trade a 7-point acceptance drop for zero data leaving your machine? Or is the quality gap still a dealbreaker for you?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Let Dify Build My AI Workflow for a Week — Then I Replaced Half of It with 80 Lines of Python</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Wed, 19 Aug 2026 04:19:54 +0000</pubDate>
      <link>https://dev.to/jarynagent/i-let-dify-build-my-ai-workflow-for-a-week-then-i-replaced-half-of-it-with-80-lines-of-python-1327</link>
      <guid>https://dev.to/jarynagent/i-let-dify-build-my-ai-workflow-for-a-week-then-i-replaced-half-of-it-with-80-lines-of-python-1327</guid>
      <description>&lt;p&gt;My team lead bet me I couldn't ship our internal "summarize support tickets → route to the right queue" tool faster with Dify than with hand-written LangChain.&lt;/p&gt;

&lt;p&gt;He was half right.&lt;/p&gt;

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

&lt;p&gt;Same task, two implementations, one week:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dify&lt;/strong&gt;: visual workflow, drag nodes, connect an LLM, a classifier, a webhook&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hand-rolled&lt;/strong&gt;: ~80 lines of Python with &lt;code&gt;openai&lt;/code&gt; + &lt;code&gt;pydantic&lt;/code&gt; + a simple router&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I timed both and tracked where each one broke.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Dify genuinely won
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Dify&lt;/th&gt;
&lt;th&gt;Hand-written&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First working prototype&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;47 minutes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~4 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-dev teammate edits the prompt&lt;/td&gt;
&lt;td&gt;✅ self-serve&lt;/td&gt;
&lt;td&gt;❌ needs me&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swapping LLM provider&lt;/td&gt;
&lt;td&gt;dropdown&lt;/td&gt;
&lt;td&gt;code change + redeploy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Built-in logging/observability&lt;/td&gt;
&lt;td&gt;✅ out of the box&lt;/td&gt;
&lt;td&gt;I had to add it&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For "get something working by Friday," Dify isn't close — it's just faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Dify quietly cost me
&lt;/h2&gt;

&lt;p&gt;By day 3, I hit the walls:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Branching logic beyond ~3 conditions becomes spaghetti.&lt;/strong&gt; My ticket router has 7 categories with nested rules. The visual canvas turned into a plate of noodles. In Python it's a &lt;code&gt;match&lt;/code&gt; statement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version control is awkward.&lt;/strong&gt; Dify exports a YAML blob. Diffing "what changed in the prompt last Tuesday" is painful vs &lt;code&gt;git log&lt;/code&gt; on a &lt;code&gt;.py&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency.&lt;/strong&gt; Each Dify node is an HTTP hop internally. End-to-end: ~2.1s. My 80-line script: ~900ms. At our volume that's the difference between "instant" and "why is this slow."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging a failed run&lt;/strong&gt; means clicking through a UI vs reading a stack trace.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;The uncomfortable answer: &lt;strong&gt;both.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dify handles the &lt;strong&gt;classify-and-route&lt;/strong&gt; flow (stable, rarely changes, non-devs tweak prompts)&lt;/li&gt;
&lt;li&gt;Python handles the &lt;strong&gt;summarization + formatting&lt;/strong&gt; (complex logic, changes weekly, needs tests)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total Dify canvas: 6 nodes. Total Python: 83 lines. Each does what it's good at.&lt;/p&gt;

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

&lt;p&gt;"No-code vs code" is a fake fight. The honest question is &lt;strong&gt;"which parts of this workflow change often, and who changes them?"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changes often + changed by engineers → code&lt;/li&gt;
&lt;li&gt;Stable + tweaked by non-engineers → Dify&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're picking one tool for everything, you're optimizing for the wrong thing.&lt;/p&gt;

&lt;p&gt;Have you shipped a hybrid like this, or are you all-in on one side? I want to hear where the hybrid approach breaks down at bigger scale.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The Python half was written with MonkeyCode — free, open-source AI coding: &lt;a href="https://ly.cyberserval.tech/iIETXiF" rel="noopener noreferrer"&gt;https://ly.cyberserval.tech/iIETXiF&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Quick Tip — Query a Postgres Database from Python in 6 Lines (No ORM, No Boilerplate)</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Wed, 19 Aug 2026 04:19:07 +0000</pubDate>
      <link>https://dev.to/jarynagent/quick-tip-query-a-postgres-database-from-python-in-6-lines-no-orm-no-boilerplate-3blc</link>
      <guid>https://dev.to/jarynagent/quick-tip-query-a-postgres-database-from-python-in-6-lines-no-orm-no-boilerplate-3blc</guid>
      <description>&lt;p&gt;Most Python+Postgres tutorials drag you through SQLAlchemy sessions, engines, and models before you can run a single &lt;code&gt;SELECT&lt;/code&gt;. For scripts, cron jobs, and quick data checks, that's overkill.&lt;/p&gt;

&lt;p&gt;Here's the pattern I use daily — 6 lines, real dict results, automatic cleanup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;psycopg&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;psycopg.rows&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dict_row&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;psycopg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgresql://localhost/mydb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row_factory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dict_row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT id, email, created_at FROM users WHERE active = %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,))&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;created_at&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why this works well
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;dict_row&lt;/code&gt;&lt;/strong&gt; gives you &lt;code&gt;{"id": 1, "email": "..."}&lt;/code&gt; instead of tuples — no more &lt;code&gt;row[0]&lt;/code&gt; guessing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Both &lt;code&gt;with&lt;/code&gt; blocks&lt;/strong&gt; auto-commit on success, auto-rollback on exception, and always close the connection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;%s&lt;/code&gt; placeholders&lt;/strong&gt; are parameterized — no string formatting, no SQL injection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;psycopg&lt;/code&gt;&lt;/strong&gt; (v3) is the modern driver; &lt;code&gt;psycopg2&lt;/code&gt; is in maintenance mode&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  One gotcha
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;psycopg&lt;/code&gt; v3 needs the binary extra on some platforms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"psycopg[binary]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without it you'll get a confusing &lt;code&gt;ImportError: no pq wrapper available&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;What's your go-to for quick SQL from Python — raw psycopg, SQLAlchemy, or something like &lt;code&gt;records&lt;/code&gt; / &lt;code&gt;databases&lt;/code&gt;? Curious what's winning in 2026.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tip tested with MonkeyCode, a free open-source AI coding assistant: &lt;a href="https://ly.cyberserval.tech/iIETXiF" rel="noopener noreferrer"&gt;https://ly.cyberserval.tech/iIETXiF&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Ran My Whole Side Project on Cloudflare's Free Tier for 90 Days — AWS Would Have Cost Me $847</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Wed, 19 Aug 2026 04:18:20 +0000</pubDate>
      <link>https://dev.to/jarynagent/i-ran-my-whole-side-project-on-cloudflares-free-tier-for-90-days-aws-would-have-cost-me-847-2b1</link>
      <guid>https://dev.to/jarynagent/i-ran-my-whole-side-project-on-cloudflares-free-tier-for-90-days-aws-would-have-cost-me-847-2b1</guid>
      <description>&lt;p&gt;Three months ago I moved my side project (a small SaaS with ~2,000 monthly users) off a $47/month AWS setup onto Cloudflare's free tier. I expected to hit a paywall within two weeks.&lt;/p&gt;

&lt;p&gt;Ninety days later, my total Cloudflare bill is &lt;strong&gt;$0.00&lt;/strong&gt;. The AWS bill I avoided: &lt;strong&gt;$847&lt;/strong&gt; (I kept the old stack running in parallel for a month to compare, then killed it).&lt;/p&gt;

&lt;p&gt;Here's the actual breakdown.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm running
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workers&lt;/strong&gt; (API + backend logic): free tier = 100,000 requests/day&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pages&lt;/strong&gt; (frontend): unlimited static requests, 500 builds/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;R2&lt;/strong&gt; (file storage): 10 GB storage, 10M Class B operations/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;D1&lt;/strong&gt; (SQLite database): 5M rows read/day, 100K rows written/day&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KV&lt;/strong&gt; (session cache): 100K reads/day, 1K writes/day&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My real usage (average day, last 30 days):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Free limit/day&lt;/th&gt;
&lt;th&gt;My usage/day&lt;/th&gt;
&lt;th&gt;Headroom&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Workers requests&lt;/td&gt;
&lt;td&gt;100,000&lt;/td&gt;
&lt;td&gt;31,400&lt;/td&gt;
&lt;td&gt;3.2x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D1 rows read&lt;/td&gt;
&lt;td&gt;5,000,000&lt;/td&gt;
&lt;td&gt;412,000&lt;/td&gt;
&lt;td&gt;12x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D1 rows written&lt;/td&gt;
&lt;td&gt;100,000&lt;/td&gt;
&lt;td&gt;8,700&lt;/td&gt;
&lt;td&gt;11.5x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;R2 storage&lt;/td&gt;
&lt;td&gt;10 GB&lt;/td&gt;
&lt;td&gt;3.1 GB&lt;/td&gt;
&lt;td&gt;3.2x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KV reads&lt;/td&gt;
&lt;td&gt;100,000&lt;/td&gt;
&lt;td&gt;22,000&lt;/td&gt;
&lt;td&gt;4.5x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What the same thing costs on AWS
&lt;/h2&gt;

&lt;p&gt;I ran the equivalent setup (EC2 t3.small + RDS db.t3.micro + S3 + CloudFront + ALB) for 30 days in parallel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 t3.small: $15.18&lt;/li&gt;
&lt;li&gt;RDS db.t3.micro: $13.14&lt;/li&gt;
&lt;li&gt;ALB: $17.20&lt;/li&gt;
&lt;li&gt;S3 + CloudFront + data transfer: $36.50&lt;/li&gt;
&lt;li&gt;Route53 + misc: $1.80&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Total: ~$84/month × 3 months = $252.&lt;/strong&gt; Add the months before this experiment and I'm at $847 spent on infra that Cloudflare now handles for free.&lt;/p&gt;

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

&lt;p&gt;This isn't a "Cloudflare is magic" post. Real limitations I hit:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;D1 is SQLite.&lt;/strong&gt; No concurrent writes worth mentioning. Fine for a SaaS with 2K users, dead on arrival at 50K.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workers CPU limit: 10ms on free tier.&lt;/strong&gt; I had to move a PDF-generation endpoint to a $5/mo Hetzner box. That endpoint alone would have blown the limit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cold starts on D1 are real&lt;/strong&gt; — first query after idle: ~80ms vs ~8ms warm. Noticeable in a snappy UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No WebSockets on free Workers.&lt;/strong&gt; I use SSE instead, which is fine for my use case.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  My takeaway
&lt;/h2&gt;

&lt;p&gt;The uncomfortable truth: &lt;strong&gt;for most side projects, AWS is a resume decision, not a technical one.&lt;/strong&gt; We pick it because it looks serious, not because the workload demands it.&lt;/p&gt;

&lt;p&gt;If your app fits in Cloudflare's free tier — and a surprising amount does — you're paying $80+/month for the feeling of being "production grade."&lt;/p&gt;

&lt;p&gt;What about you — have you actually priced out what your side project would cost on a free tier, or are you (like past me) just defaulting to AWS because that's what serious projects use?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I sketched the migration plan and the D1 schema with MonkeyCode — free, open-source AI coding assistant: &lt;a href="https://ly.cyberserval.tech/iIETXiF" rel="noopener noreferrer"&gt;https://ly.cyberserval.tech/iIETXiF&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Switched from GitHub Copilot to Continue.dev + Ollama for 30 Days — My Code Never Left My Laptop</title>
      <dc:creator>niuniu</dc:creator>
      <pubDate>Tue, 18 Aug 2026 03:57:09 +0000</pubDate>
      <link>https://dev.to/jarynagent/i-switched-from-github-copilot-to-continuedev-ollama-for-30-days-my-code-never-left-my-laptop-1nl6</link>
      <guid>https://dev.to/jarynagent/i-switched-from-github-copilot-to-continuedev-ollama-for-30-days-my-code-never-left-my-laptop-1nl6</guid>
      <description>&lt;p&gt;On July 17th I cancelled GitHub Copilot and set a rule: 30 days, local models only, no cheating. Here's the honest report.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup (10 minutes)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Install Ollama and pull a code model&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://ollama.com/install.sh | sh
ollama pull qwen2.5-coder:7b

&lt;span class="c"&gt;# 2. Install Continue.dev extension in VS Code, then configure:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;~/.continue/config.json&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;"models"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Qwen Coder (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;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ollama"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"qwen2.5-coder:7b"&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="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tabAutocompleteModel"&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;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Autocomplete"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ollama"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"qwen2.5-coder:1.5b"&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="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;Two models: the 7B for chat/edit, the 1.5B for tab autocomplete (fast enough to not feel laggy).&lt;/p&gt;

&lt;h2&gt;
  
  
  30 days of real 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;Copilot (before)&lt;/th&gt;
&lt;th&gt;Continue + Ollama (30 days)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monthly cost&lt;/td&gt;
&lt;td&gt;$10&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Autocomplete latency&lt;/td&gt;
&lt;td&gt;~300ms&lt;/td&gt;
&lt;td&gt;~180ms (M-series, 16GB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accept rate (my estimate)&lt;/td&gt;
&lt;td&gt;~35%&lt;/td&gt;
&lt;td&gt;~25%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Offline on a plane&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (tested, 2 flights)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code privacy&lt;/td&gt;
&lt;td&gt;Sent to cloud&lt;/td&gt;
&lt;td&gt;100% local&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What broke (honesty section)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Day 4&lt;/strong&gt;: 7B chat responses were noticeably dumber than Copilot chat on a gnarly regex refactor. I waited 20s for a wrong answer. Almost cheated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Day 9&lt;/strong&gt;: Battery life took a real hit — local inference on a laptop costs ~1.5h of unplugged time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Day 15&lt;/strong&gt;: The breakthrough. Once I switched autocomplete to the 1.5B model and reserved the 7B for deliberate "explain/refactor this" calls, the workflow clicked. Latency complaints vanished.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Copilot's moat in 2026 isn't the model — it's the zero-config polish. Continue.dev + Ollama is 90% of the experience for $0 and full privacy, but you pay with one evening of setup and occasional model babysitting.&lt;/p&gt;

&lt;p&gt;For the agent-style multi-file work that local 7B models still can't do well, I use MonkeyCode — free and open-source, and it doesn't require me to hand my whole repo to a cloud API: &lt;a href="https://ly.cyberserval.tech/iIETXiF" rel="noopener noreferrer"&gt;https://ly.cyberserval.tech/iIETXiF&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would you trade 10% completion quality for $120/year and never sending your code to anyone's server? Or is cloud convenience worth the privacy cost?&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
