<?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: Rene Zander</title>
    <description>The latest articles on DEV Community by Rene Zander (@reneza).</description>
    <link>https://dev.to/reneza</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%2F1138713%2F4c71b271-0320-4d6b-92a9-12e3225b72e5.jpeg</url>
      <title>DEV Community: Rene Zander</title>
      <link>https://dev.to/reneza</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/reneza"/>
    <language>en</language>
    <item>
      <title>Spend Your Human Thinking Tokens Where They Compound</title>
      <dc:creator>Rene Zander</dc:creator>
      <pubDate>Tue, 31 Mar 2026 08:32:22 +0000</pubDate>
      <link>https://dev.to/reneza/spend-your-human-thinking-tokens-where-they-compound-pf1</link>
      <guid>https://dev.to/reneza/spend-your-human-thinking-tokens-where-they-compound-pf1</guid>
      <description>&lt;p&gt;More automations running. More agents deployed. More pipelines humming in the background.&lt;/p&gt;

&lt;p&gt;I run about a dozen automated jobs. Daily briefings, proposal generation, content pipelines, data syncing, monitoring alerts. They handle a lot.&lt;/p&gt;

&lt;p&gt;But the biggest improvement to my workflow this year wasn't adding more automation. It was getting honest about where my thinking actually matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  You Have a Token Budget Too
&lt;/h2&gt;

&lt;p&gt;LLMs have context windows. Feed in too much noise and the signal degrades. The output gets worse even though you gave it more to work with.&lt;/p&gt;

&lt;p&gt;Human attention works the same way. I have maybe 4 good hours of focused thinking per day. When I spend those hours reviewing cron output or formatting documents or triaging alerts that resolve themselves, I'm burning tokens on low-value work.&lt;/p&gt;

&lt;p&gt;The quality of my actual decisions goes down. Not because the decisions got harder, but because I already used up my thinking budget on stuff that didn't need me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I Stopped Spending
&lt;/h2&gt;

&lt;p&gt;I used to review my morning briefing line by line. Check every data point, verify every summary. Then I realized: if the briefing is wrong, I'll notice when the information doesn't match reality later that day. The cost of a slightly wrong briefing at 6:30 is near zero. The cost of spending 20 minutes checking it every morning is real.&lt;/p&gt;

&lt;p&gt;Same with monitoring. I had alerts for everything. Cache refreshes, API response times, sync completions. Most of them were informational, not actionable. I stripped it down to alerts that require a decision: something broke, something is about to expire, something needs my approval before it touches an external system.&lt;/p&gt;

&lt;p&gt;Data syncing runs on a schedule. If it fails, I get one alert. I don't watch it run. I don't check the logs unless the alert fires.&lt;/p&gt;

&lt;p&gt;First drafts of anything. Cover letters, content outlines, research summaries. The AI produces a version. Sometimes it's good enough. Sometimes I rewrite half of it. But I never start from a blank page anymore, and that alone saves the hardest type of thinking: getting started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I Still Spend Every Token
&lt;/h2&gt;

&lt;p&gt;Scoping client work. An AI can research a company, summarize a job posting, draft a proposal. But deciding whether the project is actually worth pursuing? Whether the client's problem is what they say it is? That's pattern recognition built from years of seeing projects go sideways. No automation for that.&lt;/p&gt;

&lt;p&gt;Choosing what to build next. I have a backlog of 50 things I could automate, improve, or ship. The AI can't tell me which one moves the needle this week. That decision depends on context it doesn't have: what conversations I had yesterday, what I'm optimizing for this month, what feels right.&lt;/p&gt;

&lt;p&gt;Anything with my name on it that reaches another person. Proposals get edited. Posts get rewritten. Client messages get reviewed word by word. The AI drafts. I decide what actually represents me.&lt;/p&gt;

&lt;p&gt;System design decisions. Where to draw the boundary between automatic and manual. What gets a human checkpoint and what runs unsupervised. These are the highest-leverage decisions in any AI system, and they're entirely human.&lt;/p&gt;

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

&lt;p&gt;Maybe 20% of my working hours involve focused, high-stakes thinking. The rest is execution, coordination, and maintenance.&lt;/p&gt;

&lt;p&gt;Before I built these systems, that ratio was reversed. 80% thinking, 20% execution, and half the thinking was on tasks that didn't deserve it.&lt;/p&gt;

&lt;p&gt;The goal was never "automate everything." It was "protect the 20% that matters and make sure I'm not exhausted when I get there."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shift
&lt;/h2&gt;

&lt;p&gt;This isn't about working less. I work the same hours. But the distribution changed.&lt;/p&gt;

&lt;p&gt;I spend less time on decisions that don't compound. I spend more time on the ones that do. Client relationships, system architecture, strategic bets. The stuff where being sharp at 10 in the morning instead of burned out from triaging alerts actually changes the outcome.&lt;/p&gt;

&lt;p&gt;The question isn't how much your AI can do. It's whether you're spending your own thinking tokens on the right things.&lt;/p&gt;

&lt;p&gt;Where are you still spending attention that you probably shouldn't?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I help teams figure out where AI should run unsupervised and where humans still need to be in the loop. If that's a question your team is working through, let's talk: &lt;a href="https://cal.eu/reneza" rel="noopener noreferrer"&gt;cal.eu/reneza&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>AI Skills Are the New Boilerplate. They Solve Almost Nothing.</title>
      <dc:creator>Rene Zander</dc:creator>
      <pubDate>Tue, 24 Mar 2026 11:13:17 +0000</pubDate>
      <link>https://dev.to/reneza/ai-skills-are-the-new-boilerplate-they-solve-almost-nothing-4obo</link>
      <guid>https://dev.to/reneza/ai-skills-are-the-new-boilerplate-they-solve-almost-nothing-4obo</guid>
      <description>&lt;p&gt;Everyone's sharing their skill libraries right now. "Here are my 20 custom slash commands." "Check out my prompt template collection." "This skill saves me 2 hours a day."&lt;/p&gt;

&lt;p&gt;I use skills too. I have about a dozen. They handle cover letters, content pipelines, code review, commit messages. Repeatable workflows where the input and output are predictable.&lt;/p&gt;

&lt;p&gt;They cover maybe 10% of what my AI system actually does.&lt;/p&gt;

&lt;p&gt;The other 90% is the part nobody shares on social media because it's ugly. It's API integrations that break when headers change. It's state management between sessions. It's error handling for when the third-party service returns garbage. It's monitoring that pages you at 6 AM because a cron failed. It's human-in-the-loop workflows where the AI proposes and you approve before anything touches production.&lt;/p&gt;

&lt;p&gt;Skills can't solve this. Every client, every codebase, every problem has different infrastructure underneath. A skill is a template. The work is everything the template doesn't cover.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Skills Actually Are
&lt;/h2&gt;

&lt;p&gt;A skill is a saved prompt with some structure. Input goes in, the agent follows instructions, output comes out. It works when the task is the same shape every time.&lt;/p&gt;

&lt;p&gt;"Generate a cover letter from this job posting." Same structure, different content. Perfect skill.&lt;/p&gt;

&lt;p&gt;"Debug why the webhook stopped firing after the API provider changed their auth flow." No skill for that. Every instance is different. The agent needs to read logs, trace requests, understand the specific integration, and propose a fix that accounts for your deployment setup. That's infrastructure knowledge, not a prompt template.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 90% Nobody Demos
&lt;/h2&gt;

&lt;p&gt;Here's what actually keeps my system running day to day.&lt;/p&gt;

&lt;p&gt;A server process that syncs data from multiple APIs, caches it locally, and exposes it to agents through a unified interface. When an API changes its response format, I fix the parser. No skill for that.&lt;/p&gt;

&lt;p&gt;Scheduled jobs that run without any agent session. They pull data, generate reports, send notifications, and alert me when something fails. The agent isn't even involved. It's just cron, a script, and an alert channel.&lt;/p&gt;

&lt;p&gt;Approval workflows where the AI researches options, presents them with rationale, and waits for a human decision before executing. The approval mechanism is buttons in a chat app. The execution layer calls APIs to star repositories, follow users, post comments. The plumbing between "AI suggested it" and "it actually happened" is custom for every use case.&lt;/p&gt;

&lt;p&gt;State that persists between sessions. Not agent memory. Infrastructure state. Cache files with TTLs. Vector indexes that get rebuilt nightly. Configuration that lives in flat files because a database would be overkill.&lt;/p&gt;

&lt;p&gt;None of this fits in a skill. It's bespoke infrastructure that exists because the specific problem required it.&lt;/p&gt;

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

&lt;p&gt;The skills hype creates a misleading impression of what production AI work looks like. Someone sees a collection of 30 slash commands and thinks: that's the system. It's not. It's the tip.&lt;/p&gt;

&lt;p&gt;The system is the integration layer. The error handling. The monitoring. The state management. The human-in-the-loop controls. The deployment. The part where you wake up and the thing is still running, handling edge cases the skill never anticipated.&lt;/p&gt;

&lt;p&gt;If you're evaluating someone's AI engineering capability, don't ask how many skills they have. Ask what happens when the skill fails. Ask what runs when nobody's in a session. Ask how state persists between interactions. That's where the actual engineering lives.&lt;/p&gt;

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

&lt;p&gt;I spend maybe 5% of my time writing new skills. I spend the rest building and maintaining the infrastructure that makes skills useful in the first place.&lt;/p&gt;

&lt;p&gt;A skill that generates a cover letter is worthless without the task management system that tracks proposals, the message log that maintains conversation history, and the pipeline that routes everything to the right place.&lt;/p&gt;

&lt;p&gt;A skill that creates a content draft is worthless without the publishing pipeline, the banner generation, the cross-platform distribution, and the editorial calendar that decides what to write next.&lt;/p&gt;

&lt;p&gt;The skill is the last mile. The infrastructure is the entire road.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Question
&lt;/h2&gt;

&lt;p&gt;Next time you see someone demo their skill collection, ask yourself: what's underneath? What happens between sessions? What runs at 4 AM? What breaks, and who gets paged?&lt;/p&gt;

&lt;p&gt;That's the 90%. That's the actual work.&lt;/p&gt;




&lt;p&gt;I build production AI infrastructure, not prompt collections. If your team needs the 90% that skills don't cover, let's talk: &lt;a href="https://cal.eu/reneza" rel="noopener noreferrer"&gt;cal.eu/reneza&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>How I Built a Business Email Agent with Compliance Controls in Go</title>
      <dc:creator>Rene Zander</dc:creator>
      <pubDate>Sat, 21 Mar 2026 12:49:31 +0000</pubDate>
      <link>https://dev.to/reneza/how-i-built-a-business-email-agent-with-compliance-controls-in-go-1gci</link>
      <guid>https://dev.to/reneza/how-i-built-a-business-email-agent-with-compliance-controls-in-go-1gci</guid>
      <description>&lt;p&gt;Every few weeks another AI agent product launches that can "handle your email." Dispatch, OpenClaw, and a dozen others promise to read, summarize, and reply on your behalf.&lt;/p&gt;

&lt;p&gt;They work fine for personal use. But the moment you try to use them for business operations, three problems show up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No spending controls.&lt;/strong&gt; The agent calls an LLM as many times as it wants. You find out what it cost at the end of the month.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No approval flow.&lt;/strong&gt; It either sends emails autonomously or it doesn't. There's no "show me the draft, let me approve it" step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No audit trail.&lt;/strong&gt; If a client asks "why did your system send me this?", you have no answer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I needed an email agent for my consulting business that could triage inbound mail, draft replies, and digest threads. But I also needed to explain every action it took to a client if asked. So I built one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core constraint: AI never executes
&lt;/h2&gt;

&lt;p&gt;The first decision was architectural. In most agent frameworks, the LLM decides what to do &lt;em&gt;and&lt;/em&gt; does it. Tool calling, function execution, chain-of-thought action loops.&lt;/p&gt;

&lt;p&gt;I went the other way. &lt;strong&gt;The LLM classifies and drafts. Deterministic code executes.&lt;/strong&gt; Every side effect (sending an email, posting a notification, writing a log) is plain Go code with explicit control flow. The LLM is a function call that takes text in and returns structured JSON out. Nothing more.&lt;/p&gt;

&lt;p&gt;This matters because it makes the system auditable. When something goes wrong, you read the pipeline definition, not a chat transcript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pipelines, not prompts
&lt;/h2&gt;

&lt;p&gt;Every automation is a YAML pipeline. Here's a simplified email digest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;email-digest&lt;/span&gt;
    &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30m&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fetch-unread&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deterministic&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gmail_unread&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;summarize&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ai&lt;/span&gt;
        &lt;span class="na"&gt;skill&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;email-digest&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;report&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deterministic&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;notify&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three step types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;deterministic&lt;/strong&gt;: Plain code. Fetch emails, send notifications, write logs. No tokens, instant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ai&lt;/strong&gt;: Calls an LLM with a skill template. Returns structured output. Token-budgeted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;approval&lt;/strong&gt;: Pauses the pipeline and asks a human to approve, skip, or edit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight: most of what an "email agent" does is not AI. It's polling an API, parsing MIME, filtering by label, formatting output. The AI part is a small step in the middle that classifies or summarizes. Treating it as a pipeline step instead of the orchestrator keeps costs down and behavior predictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Token budgets as circuit breakers
&lt;/h2&gt;

&lt;p&gt;Every AI step runs inside three budget boundaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;budgets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;per_step_tokens&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2048&lt;/span&gt;
  &lt;span class="na"&gt;per_pipeline_tokens&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10000&lt;/span&gt;
  &lt;span class="na"&gt;per_day_tokens&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a step exceeds its token limit, it fails. If a pipeline exceeds its limit, it stops. If the daily limit is hit, the engine pauses all pipelines until midnight.&lt;/p&gt;

&lt;p&gt;This is a circuit breaker, not a suggestion. I've seen agents get stuck in retry loops that burn through $50 in tokens before anyone notices. A hard ceiling at the engine level prevents that by design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Human-in-the-loop on every outbound action
&lt;/h2&gt;

&lt;p&gt;The email connector has three permission levels: &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;draft&lt;/code&gt;, and &lt;code&gt;send&lt;/code&gt;. Even at the &lt;code&gt;send&lt;/code&gt; level, outbound emails go through an approval step first.&lt;/p&gt;

&lt;p&gt;The approval flow works through a messaging bot. The operator gets the draft with three options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Approve&lt;/strong&gt;: Send immediately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skip&lt;/strong&gt;: Cancel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adjust&lt;/strong&gt;: Edit the text, then approve.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's a 4-hour timeout. If no one approves, the action is logged and dropped. This is non-negotiable for business use. An autonomous email agent that sends on your behalf without approval is a liability.&lt;/p&gt;

&lt;p&gt;The approval channel itself has security controls: allowed user IDs, rate limiting per user, input length caps, and markdown stripping to prevent prompt boundary injection through the operator interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gmail connector
&lt;/h2&gt;

&lt;p&gt;The email connector is ~400 lines of Go. All outbound polling, no webhooks, no open ports. It handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OAuth 2.0 with automatic token refresh&lt;/li&gt;
&lt;li&gt;Base64 MIME decoding with multipart handling&lt;/li&gt;
&lt;li&gt;Thread reconstruction in chronological order&lt;/li&gt;
&lt;li&gt;RFC 2822 compliant reply construction (In-Reply-To, References headers)&lt;/li&gt;
&lt;li&gt;Body truncation for token efficiency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Permission scoping is enforced at the connector level. If the config says &lt;code&gt;permission: read&lt;/code&gt;, the connector physically cannot call the send endpoint. It's not a policy check, it's a code path that doesn't exist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;GmailConfig&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;TokenPath&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`yaml:"token_path"`&lt;/span&gt;
    &lt;span class="n"&gt;Permission&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`yaml:"permission"`&lt;/span&gt; &lt;span class="c"&gt;// read | draft | send&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Skills: reusable AI templates
&lt;/h2&gt;

&lt;p&gt;AI steps reference skill files instead of inline prompts. A skill is a YAML template with a role, a prompt, and an optional output schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;email-digest&lt;/span&gt;
&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;classifier&lt;/span&gt;
&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;Summarize these unread emails. For each:&lt;/span&gt;
  &lt;span class="s"&gt;[priority] Sender - Subject - what they need&lt;/span&gt;
  &lt;span class="s"&gt;Priority: HIGH = needs response today,&lt;/span&gt;
  &lt;span class="s"&gt;MED = this week, LOW = informational&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output schemas enforce structure. If the LLM returns JSON that doesn't match the schema, the step fails instead of passing garbage downstream. This matters more than people think. An unvalidated LLM response in an automation pipeline is a bug waiting to happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Go
&lt;/h2&gt;

&lt;p&gt;Single binary. Cross-compile for the client's infrastructure. No runtime dependencies.&lt;/p&gt;

&lt;p&gt;The entire engine runs on a 2-core VPS for under $5/month. There's no database server, no message queue, no container orchestration. SQLite for state, YAML for config, one binary for the engine. Deploy with &lt;code&gt;scp&lt;/code&gt; and a systemd unit.&lt;/p&gt;

&lt;p&gt;For a tool that runs on client infrastructure, operational simplicity is a feature. Every dependency is a support ticket waiting to happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this compares to Dispatch and OpenClaw
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Dispatch&lt;/th&gt;
&lt;th&gt;OpenClaw&lt;/th&gt;
&lt;th&gt;FixClaw&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Target&lt;/td&gt;
&lt;td&gt;Personal productivity&lt;/td&gt;
&lt;td&gt;Personal AI agent&lt;/td&gt;
&lt;td&gt;Business operations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token controls&lt;/td&gt;
&lt;td&gt;None (subscription)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Per-step, per-pipeline, per-day budgets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human approval&lt;/td&gt;
&lt;td&gt;Pause on destructive&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;Every outbound action&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data residency&lt;/td&gt;
&lt;td&gt;Cloud&lt;/td&gt;
&lt;td&gt;Self-hosted&lt;/td&gt;
&lt;td&gt;Self-hosted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration&lt;/td&gt;
&lt;td&gt;Natural language&lt;/td&gt;
&lt;td&gt;Natural language&lt;/td&gt;
&lt;td&gt;YAML (version-controlled, auditable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit trail&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Full action + decision logging&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Dispatch and OpenClaw are good products for what they do. But "what they do" is personal productivity. The moment you need to explain to a client what your automation did and why, you need governance controls that personal tools don't have.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Most agent complexity is accidental.&lt;/strong&gt; The LLM doesn't need to decide what to do next. You know what to do next. Write it in a pipeline. Use the LLM for the one step that actually requires language understanding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Token budgets change how you design prompts.&lt;/strong&gt; When there's a hard ceiling, you stop sending full email bodies and start truncating aggressively. You pick smaller models for classification. You realize 90% of your use cases work fine with a fast, cheap model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Human-in-the-loop is not a UX compromise, it's a product feature.&lt;/strong&gt; Clients don't want autonomous agents sending emails on their behalf. They want a system that does the thinking and lets them press the button. The approval step isn't a limitation. It's the reason they trust it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;FixClaw is open source and written in Go. If you're building business automations that need compliance controls, check it out on &lt;a href="https://github.com/renezander030/fixclaw" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>ai</category>
      <category>email</category>
      <category>automation</category>
    </item>
    <item>
      <title>Detecting When Smart Money Stops Being Smart</title>
      <dc:creator>Rene Zander</dc:creator>
      <pubDate>Tue, 17 Mar 2026 10:26:14 +0000</pubDate>
      <link>https://dev.to/reneza/detecting-when-smart-money-stops-being-smart-21n3</link>
      <guid>https://dev.to/reneza/detecting-when-smart-money-stops-being-smart-21n3</guid>
      <description>&lt;p&gt;Following a profitable wallet is easy. Knowing when to unfollow it is where the money is.&lt;/p&gt;

&lt;p&gt;I learned this the hard way. Not in crypto, but in forex. Years ago I built trading systems that scraped signals from profitable traders and mirrored their positions. It worked until it didn't. The problem was never finding good traders to follow. The problem was staying too long after they stopped performing.&lt;/p&gt;

&lt;p&gt;The same pattern repeats in on-chain copy trading. Someone finds a wallet with a 70% win rate, follows every move, and six weeks later wonders why they're bleeding. The wallet didn't get hacked. The market shifted and the strategy stopped working.&lt;/p&gt;

&lt;p&gt;Nobody talks about this part.&lt;/p&gt;

&lt;h3&gt;
  
  
  The decay problem
&lt;/h3&gt;

&lt;p&gt;Every trading strategy has a shelf life. A wallet that's profitable today is running a strategy tuned to current market conditions. When conditions change, the strategy breaks. Sometimes gradually, sometimes overnight.&lt;/p&gt;

&lt;p&gt;In forex I watched this happen in real time. A signal provider would post a 40% return over three months. Followers would pile in during month four. By month six the drawdown had wiped most of the gains. The provider's edge was gone but the followers didn't know because they were looking at cumulative PnL, not recent performance.&lt;/p&gt;

&lt;p&gt;On-chain it's the same dynamic but harder to detect because the data is messier. You're not looking at clean trade logs. You're parsing token swaps, liquidity events, and contract interactions, then trying to figure out if the pattern still holds.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to actually measure
&lt;/h3&gt;

&lt;p&gt;When I built a detection system for this, I focused on three metrics that signal regime change:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Win rate over a rolling window.&lt;/strong&gt; Not all-time. A wallet with a 65% all-time win rate that's been running at 40% for the last three weeks is in trouble. The all-time number hides the decay.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Average return per trade, recent vs historical.&lt;/strong&gt; If the average return is shrinking even while the win rate holds, the edge is thinning. The wallet is still picking winners but the magnitude is dropping. This is the earliest warning sign.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trade frequency changes.&lt;/strong&gt; A wallet that was trading daily and suddenly goes quiet for a week might be recalibrating. Or it might be done. Either way, the pattern you were following no longer exists.&lt;/p&gt;

&lt;p&gt;None of these metrics work in isolation. A drop in win rate during a broad market pullback means nothing. But a drop in win rate while similar wallets maintain theirs, that's a signal.&lt;/p&gt;

&lt;h3&gt;
  
  
  The threshold problem
&lt;/h3&gt;

&lt;p&gt;The hardest part isn't collecting the data. It's deciding what counts as a regime change versus normal variance.&lt;/p&gt;

&lt;p&gt;Set the thresholds too tight and you're unfollowing wallets after every bad week. Too loose and you catch the decline three weeks after it started. I went through several iterations before landing on something useful: compare the wallet's recent performance against its own historical baseline, not against an absolute number.&lt;/p&gt;

&lt;p&gt;A wallet that normally runs a 55% win rate dropping to 45% is a different signal than a wallet that normally runs 75% dropping to 65%. Both dropped 10 points, but the first one is within normal variance and the second one is a structural shift.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to actually stop following
&lt;/h3&gt;

&lt;p&gt;The detection is one thing. Acting on it is another.&lt;/p&gt;

&lt;p&gt;The instinct is to wait. "Maybe it's just a bad week." That's the same instinct that kept me in losing forex signals for months. The data was clear but the hope was louder.&lt;/p&gt;

&lt;p&gt;What worked for me: automate the alert, not the action. The system flags when a wallet crosses its regime change threshold. I review it, check the context (is the whole market down or just this wallet?), and decide. But the flag forces the decision. Without it, I'd never look.&lt;/p&gt;

&lt;p&gt;Most people in DeFi are still following wallets based on a snapshot of past performance. They find a wallet on a leaderboard, follow it, and never re-evaluate. That's not a strategy. That's a bet that conditions never change.&lt;/p&gt;

&lt;p&gt;The edge isn't in finding smart money. There are tools for that everywhere. The edge is in knowing when smart money stops being smart for the current market, and stepping aside before the losses compound.&lt;/p&gt;

&lt;p&gt;If you're thinking about building something similar or want to talk through the detection approach, feel free to reach out: &lt;a href="https://cal.eu/reneza" rel="noopener noreferrer"&gt;cal.eu/reneza&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>defi</category>
      <category>trading</category>
      <category>web3</category>
    </item>
    <item>
      <title>Your Vector Database Decision Is Simpler Than You Think</title>
      <dc:creator>Rene Zander</dc:creator>
      <pubDate>Tue, 17 Mar 2026 07:41:59 +0000</pubDate>
      <link>https://dev.to/reneza/your-vector-database-decision-is-simpler-than-you-think-3ape</link>
      <guid>https://dev.to/reneza/your-vector-database-decision-is-simpler-than-you-think-3ape</guid>
      <description>&lt;p&gt;Every week someone asks which vector database they should use. The answer is almost always "it depends on three things," and none of them are throughput benchmarks.&lt;/p&gt;

&lt;p&gt;I run semantic search in production on a single VPS. Over a thousand items indexed, embeddings generated on the same machine, queries return in under a second. But that setup only works because of the constraints I'm operating in. Change the constraints and the answer changes completely.&lt;/p&gt;

&lt;p&gt;Here's how I think about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The overchoice problem
&lt;/h3&gt;

&lt;p&gt;There are dozens of vector databases now. Every one of them publishes benchmarks showing millions of vectors queried in milliseconds. That's great if you're building a search engine for the entire internet. Most of us aren't.&lt;/p&gt;

&lt;p&gt;The benchmarks test throughput at scale. What they don't test is: can this thing run on the same box as your application without eating all the memory? Can you set it up in ten minutes? Does it need a cluster?&lt;/p&gt;

&lt;p&gt;Those are the questions that actually matter when you're picking one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 1: Local device, small dataset, ephemeral
&lt;/h3&gt;

&lt;p&gt;You have a CLI tool or a local application. Your data is a few hundred markdown files or JSON documents. The user runs it on their laptop.&lt;/p&gt;

&lt;p&gt;You don't need a database. Load the vectors into memory on startup, compute cosine similarity, done. A flat array of float32 embeddings and a brute-force search will outperform any database at this scale because there's zero overhead. No process to manage, no port to configure, no persistence to worry about.&lt;/p&gt;

&lt;p&gt;Pre-compute your embeddings at build time or on first run, store them alongside the source files. When the data changes, regenerate. At a few hundred items this takes seconds.&lt;/p&gt;

&lt;p&gt;The mistake people make here is reaching for a database because it feels like the "proper" way. It's not. It's unnecessary complexity for a problem that fits in a single array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 2: Small VPS, thousands of items, needs persistence
&lt;/h3&gt;

&lt;p&gt;Now things change. Your data lives behind an API. It updates throughout the day. You need search results to reflect changes within minutes, not hours. The whole thing runs on a VPS with maybe 2GB of RAM, shared with other services.&lt;/p&gt;

&lt;p&gt;This is where a lightweight vector database process makes sense. Something that runs as a single binary, stores vectors on disk, serves queries over a local HTTP API. You don't need clustering or replication. You need something that starts fast, uses a few hundred MB of RAM, and doesn't crash when you restart other services on the same box.&lt;/p&gt;

&lt;p&gt;The key decisions here: embedding model runs locally or via API? If your VPS has enough RAM, running a small embedding model locally saves you per-request API costs and latency. If RAM is tight, use an embedding API and only store the resulting vectors locally.&lt;/p&gt;

&lt;p&gt;Change detection matters at this scale. You don't want to re-embed everything on every sync. Hash the source content, compare to what's stored, only embed what changed. This keeps your sync jobs fast and your API costs predictable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 3: Multi-service, millions of vectors, high availability
&lt;/h3&gt;

&lt;p&gt;This is where the benchmarks actually apply. Multiple services querying the same vector index. Data measured in millions of items. Uptime requirements that mean you can't tolerate a single-process restart.&lt;/p&gt;

&lt;p&gt;At this scale you need a managed service or a self-hosted cluster. Replication, sharding, automatic failover. The operational overhead is real but justified because downtime now costs money.&lt;/p&gt;

&lt;p&gt;Most teams jump here first because it looks professional. But if your dataset fits in 2GB of RAM and you have one service querying it, you're paying for complexity you don't need.&lt;/p&gt;

&lt;h3&gt;
  
  
  The three questions
&lt;/h3&gt;

&lt;p&gt;Before looking at any product page, answer these:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does the data live?&lt;/strong&gt; If it's local files that rarely change, stay in-memory. If it's behind an API that updates constantly, you need a persistent store.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How much RAM can you spare?&lt;/strong&gt; This determines whether you run embeddings locally or call an API, and whether your database runs in-process or as a separate service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do you need persistence or is ephemeral fine?&lt;/strong&gt; If you can regenerate everything from source in seconds, skip the database. If regeneration takes minutes or hours, persist.&lt;/p&gt;

&lt;p&gt;These three questions eliminate 80% of the options before you read a single benchmark.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start from the environment
&lt;/h3&gt;

&lt;p&gt;The pattern I keep seeing is people evaluating vector databases by features and benchmarks, then trying to fit the winner into their deployment. It works the other way around. Start from your environment, your constraints, your data volume. The right answer usually becomes obvious.&lt;/p&gt;

&lt;p&gt;The comparison articles won't tell you this because they can't. They don't know if you're running on a laptop, a $5 VPS, or a Kubernetes cluster. You do.&lt;/p&gt;

&lt;p&gt;If you're building something with semantic search and want to think through which approach fits your setup, I'm always up for a quick conversation: &lt;a href="https://cal.eu/reneza" rel="noopener noreferrer"&gt;cal.eu/reneza&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>vectordatabase</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>I Run 10 AI Agents in Production. They're All Bash Scripts.</title>
      <dc:creator>Rene Zander</dc:creator>
      <pubDate>Thu, 12 Mar 2026 14:29:44 +0000</pubDate>
      <link>https://dev.to/reneza/i-run-10-ai-agents-in-production-theyre-all-bash-scripts-df2</link>
      <guid>https://dev.to/reneza/i-run-10-ai-agents-in-production-theyre-all-bash-scripts-df2</guid>
      <description>&lt;p&gt;A week ago I wrote about &lt;a href="https://dev.to/renezander030/lots-of-people-are-demoing-ai-agents-almost-nobodys-shipping-them-the-right-way-5c10"&gt;shipping AI agents the right way&lt;/a&gt;. That piece was about the harness: quality gates, token economics, multi-model verification. The stuff that separates demos from production.&lt;/p&gt;

&lt;p&gt;A lot of people resonated with it. But I left out the part that actually eats most of my time: keeping the boring stuff running.&lt;/p&gt;

&lt;p&gt;So let me walk you through what production AI agents actually look like when the conference talk is over.&lt;/p&gt;

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

&lt;p&gt;I run about ten agents in production. They handle things like daily briefings, team follow-ups, task classification, weekly status reports, and job screening. None of them are impressive. All of them are useful.&lt;/p&gt;

&lt;p&gt;The architecture for every single one is the same:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trigger &amp;gt; Fetch data &amp;gt; Scoped prompt &amp;gt; Write output &amp;gt; Notify&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A scheduled job fires. The agent pulls data from a task system, a calendar, an inbox, whatever it needs. A scoped prompt with a token budget processes that data. The result gets written back or sent as a notification.&lt;/p&gt;

&lt;p&gt;That's it. No framework. No orchestration layer. No agent-to-agent communication protocol. Each agent is a standalone script with a timeout and a budget cap.&lt;/p&gt;

&lt;p&gt;The ones that run daily cost about $1 per run. The weekly planner, which needs more context, costs about $5. The job screener uses a smaller model and comes in at $0.25. Monthly total across everything: somewhere around $80.&lt;/p&gt;

&lt;h2&gt;
  
  
  State is the whole game
&lt;/h2&gt;

&lt;p&gt;The interesting part of running agents isn't the LLM call. It's everything around it.&lt;/p&gt;

&lt;p&gt;One of my agents tracks which emails it already processed. It maintains a list of the last 500 message IDs. If that list gets corrupted, every email gets reprocessed and I'm flooded with duplicate notifications. If it gets wiped, same thing.&lt;/p&gt;

&lt;p&gt;Another agent maintains a vector index. Every night, a sync job pulls all tasks, checks which ones changed since the last run, re-embeds only those, and updates the index. Smart sync means it skips tasks where only metadata changed. Without that optimization, the job would take 30 minutes instead of 30 seconds.&lt;/p&gt;

&lt;p&gt;A third agent prepends follow-up messages to task notes, separated by date markers. It never deletes old entries. The history is the context for the next run. Mess with the format and the agent loses its memory.&lt;/p&gt;

&lt;p&gt;None of this is AI work. It's state management. The LLM call is the easy part.&lt;/p&gt;

&lt;h2&gt;
  
  
  The maintenance nobody warns you about
&lt;/h2&gt;

&lt;p&gt;This is what I wish someone had told me before I started: the data your agents pull from and write to needs constant housekeeping.&lt;/p&gt;

&lt;p&gt;Task descriptions get stale. Context windows bloat because old entries pile up. Duplicate state creeps in when two agents touch the same data. Embeddings drift as your task descriptions evolve.&lt;/p&gt;

&lt;p&gt;I spend more time maintaining the data around my agents than I spend on the agents themselves. Trimming old entries, cleaning up state files, making sure the vector index stays in sync with the source of truth.&lt;/p&gt;

&lt;p&gt;It's the same kind of work you do with any data pipeline. But nobody frames it that way because "AI agent" sounds more exciting than "scheduled ETL job with an LLM in the middle."&lt;/p&gt;

&lt;h2&gt;
  
  
  Token economics shape everything
&lt;/h2&gt;

&lt;p&gt;Your architecture follows from your token budget, not the other way around.&lt;/p&gt;

&lt;p&gt;I learned this the hard way. My first agent design was a single mega-prompt that tried to do everything: read tasks, check calendar, scan inbox, generate a plan, write follow-ups. It worked. It also burned through tokens like they were free and hallucinated more than I was comfortable with.&lt;/p&gt;

&lt;p&gt;Now every agent has a single job. Small context, scoped prompt, hard token limit. The job screener doesn't need to know about my calendar. The weekly planner doesn't need to see my inbox. Isolation isn't just cheaper. It's more reliable.&lt;/p&gt;

&lt;p&gt;The cost breakdown matters because it changes your design decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A $0.25 agent can run four times a day. A $5 agent runs once a week.&lt;/li&gt;
&lt;li&gt;A fast, cheap model handles screening. A slower, expensive model handles planning.&lt;/li&gt;
&lt;li&gt;If an agent costs more than $2 per run, I look at whether the prompt can be tighter.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Framework vs. no framework
&lt;/h2&gt;

&lt;p&gt;I tried frameworks. They lasted about three months.&lt;/p&gt;

&lt;p&gt;The problem wasn't capability. The frameworks could do everything I needed. The problem was that every failure mode became a framework debugging session instead of a straightforward script fix.&lt;/p&gt;

&lt;p&gt;A shell script fails: I read the log, find the error, fix the line. Done.&lt;/p&gt;

&lt;p&gt;A framework agent fails: I dig through abstraction layers, figure out which middleware swallowed the error, check whether the state manager persisted something weird, and then fix the line.&lt;/p&gt;

&lt;p&gt;Same fix at the end. Ten times the debugging surface.&lt;/p&gt;

&lt;p&gt;My current stack is scheduled jobs, shell scripts calling an LLM API, and log files. It has fewer moving parts than most people's "hello world" agent demos. And it's been running stable for months.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd build differently
&lt;/h2&gt;

&lt;p&gt;If I started over:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State management first.&lt;/strong&gt; Before writing a single prompt, I'd design how every agent tracks what it already did, what changed since last run, and where it writes output. This is the foundation everything else sits on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One agent, one job.&lt;/strong&gt; No multi-purpose agents. The overhead of running five cheap agents is lower than debugging one expensive agent that does five things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scheduled over event-driven.&lt;/strong&gt; For anything that happens on a predictable cadence, a timer is simpler and more reliable than a webhook chain. Event-driven has its place, but most of my agents don't need it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Budget caps from day one.&lt;/strong&gt; Every agent gets a hard spending limit. If it hits the cap, it fails loudly instead of running up a bill.&lt;/p&gt;




&lt;p&gt;I've been building and running these systems for a while now. If you're working through similar problems, or thinking about moving agents from demo to production, I'm always up for a conversation: &lt;a href="https://cal.eu/reneza" rel="noopener noreferrer"&gt;cal.eu/reneza&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>automation</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Lots Of People Are Demoing AI Agents. Almost Nobody's Shipping Them The Right Way.</title>
      <dc:creator>Rene Zander</dc:creator>
      <pubDate>Wed, 04 Mar 2026 10:56:24 +0000</pubDate>
      <link>https://dev.to/reneza/lots-of-people-are-demoing-ai-agents-almost-nobodys-shipping-them-the-right-way-5c10</link>
      <guid>https://dev.to/reneza/lots-of-people-are-demoing-ai-agents-almost-nobodys-shipping-them-the-right-way-5c10</guid>
      <description>&lt;p&gt;Lots of people are demoing AI agents. Almost nobody's shipping them the right way.&lt;/p&gt;

&lt;p&gt;Conference stages are packed with live demos of agents writing Terraform, spinning up Kubernetes clusters, and generating Helm charts on command. The audience claps. The tweet goes viral. And then... nothing ships.&lt;/p&gt;

&lt;p&gt;Here's the uncomfortable truth: the gap between "look what my agent can do" and "this runs in production every day" is enormous. I've been on both sides. I spent years as an Enterprise Architect watching organizations spin up AI pilots that never graduated. Now I run my own infrastructure with Claude as the core agent — not as a demo, not as a proof of concept, but as the actual engine that keeps things moving.&lt;/p&gt;

&lt;p&gt;This is how I did it, and what most people are getting wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: agents without harnesses
&lt;/h2&gt;

&lt;p&gt;Here's a stat that should bother you: 89% of teams running AI agents have observability. Only 52% have evals.&lt;/p&gt;

&lt;p&gt;Read that again. The industry built agents that can generate Terraform, write Helm charts, and scaffold entire CI pipelines. Impressive stuff. But almost nobody built the harness to know whether the output is actually safe to ship.&lt;/p&gt;

&lt;p&gt;We gave AI agents the power to write infrastructure code, then forgot to build the quality gates that tell us if that code will blow up in production. That's not an AI problem — that's an engineering problem. And it's the reason most agent deployments are still stuck in pilot purgatory.&lt;/p&gt;

&lt;p&gt;Observability tells you what happened. Evals tell you whether what happened was &lt;em&gt;correct&lt;/em&gt;. Without evals, you're flying blind with an autopilot you can't verify.&lt;/p&gt;

&lt;h2&gt;
  
  
  My approach: build the pipeline around AI
&lt;/h2&gt;

&lt;p&gt;Most teams bolt AI onto their existing pipeline. They add a Copilot here, an agent there, maybe a ChatGPT wrapper that generates boilerplate. The pipeline stays the same — AI is just a faster typist.&lt;/p&gt;

&lt;p&gt;I did the opposite. I built the pipeline around AI from the ground up.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Claude is the core agent.&lt;/strong&gt; Not an assistant, not a sidebar. The primary operator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The developer experience is optimized for Claude.&lt;/strong&gt; Every prompt, every constraint, every guardrail is designed for how the agent works — not retrofitted onto a human workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every dev area has a custom CLI.&lt;/strong&gt; Task management, deployments, monitoring — each domain has its own purpose-built command-line interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The infra is fully declarative.&lt;/strong&gt; Define the desired state, and it deploys. No manual steps, no click-ops.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent isn't an add-on. It's the engine. That distinction matters because it changes how you think about every other part of the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  The harness: trust, but verify — every single time
&lt;/h2&gt;

&lt;p&gt;If you take one thing from this article, let it be this: &lt;strong&gt;the harness is more important than the agent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An AI agent without quality gates is a liability. A mediocre agent with a tight harness will outperform a brilliant agent running unchecked. Here's what my harness looks like — all local, all pre-commit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linters run automatically&lt;/strong&gt; via Husky pre-commit hooks. No exceptions, no skipping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unit tests execute before code leaves the machine.&lt;/strong&gt; If tests fail, the commit is rejected. Period.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit verification prompts.&lt;/strong&gt; "Did you test this?" and "Did you verify the data flow end-to-end?" are baked into the workflow, not left to human memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice what's missing? A remote CI server.&lt;/p&gt;

&lt;p&gt;The gates are on the dev machine. By the time code gets pushed, it's already passed linting, testing, and verification. This isn't about skipping CI — it's about shifting quality left to the point where the agent operates. If the agent generates bad code, it gets caught before it ever leaves my laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Token economics: stop wasting 80% of your budget
&lt;/h2&gt;

&lt;p&gt;Most people running AI agents are hemorrhaging tokens. They pipe everything through MCP (Model Context Protocol), load massive contexts, and wonder why their agent bills look like cloud computing invoices from 2015.&lt;/p&gt;

&lt;p&gt;My rules for token efficiency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CLI over MCP — every time.&lt;/strong&gt; A well-designed CLI returns exactly what the agent needs in a fraction of the tokens. MCP is flexible but verbose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port MCPs to lightweight CLIs.&lt;/strong&gt; If you're using an MCP server for a specific domain, ask yourself: could this be a 50-line CLI script that returns structured output? Usually, yes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purpose-built CLIs per dev area.&lt;/strong&gt; One CLI for task management, one for deployments, one for monitoring. Each returns minimal, structured data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fewer tokens = faster = cheaper.&lt;/strong&gt; This isn't just about cost. Smaller contexts mean faster responses and fewer hallucinations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the bottom line: if your agent workflow costs more than the engineer it replaces, you haven't optimized the process. You've just automated the waste.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-model by design: one model is a single point of failure
&lt;/h2&gt;

&lt;p&gt;This is the part most people don't want to hear: running everything through a single model is a risk.&lt;/p&gt;

&lt;p&gt;One model means one set of biases, one set of blind spots, one failure mode. That's fine for a chatbot. It's not fine for infrastructure.&lt;/p&gt;

&lt;p&gt;My setup uses Claude as the primary agent, but delegates coding tasks to Codex. A cheap Plus plan covers most of the review work. But here's where it gets interesting:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Claude drafts the plan.&lt;/strong&gt; Architecture decisions, task breakdown, implementation strategy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Codex reviews before execution.&lt;/strong&gt; A different model with different training data and different assumptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different model = different blind spots.&lt;/strong&gt; What Claude accepts without question, Codex might flag. And vice versa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The review catches assumptions the primary agent won't question.&lt;/strong&gt; This is the AI equivalent of a code review — you want a different perspective, not an echo chamber.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Single-model pipelines are the new single point of failure. If your entire infrastructure workflow depends on one model's judgment, you've built a fragile system with extra steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  The vertical: insourcing CI
&lt;/h2&gt;

&lt;p&gt;Once the harness is tight and the token economics make sense, something interesting becomes possible: you can insource the entire CI pipeline.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Build happens locally.&lt;/strong&gt; No waiting for remote runners to spin up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker images push straight to prod.&lt;/strong&gt; The build artifact goes directly where it needs to go.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infra is declarative — define = deploy.&lt;/strong&gt; Write the desired state, and the system converges to it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No waiting for CI server queues.&lt;/strong&gt; When you're a team of one (plus agents), a CI queue is just latency with no upside.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This only works because the harness is tight. Pre-commit hooks, linters, and tests give you the confidence to ship from your laptop. Without those gates, shipping from local would be reckless. With them, it's the fastest path to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  What most people get wrong
&lt;/h2&gt;

&lt;p&gt;They treat the agent like a chatbot. That's the root cause of most failed agent deployments.&lt;/p&gt;

&lt;p&gt;Here's the pattern I see over and over:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What people do&lt;/th&gt;
&lt;th&gt;What actually works&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ask Claude to "write me some Terraform"&lt;/td&gt;
&lt;td&gt;Build a DX where Claude operates inside constraints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trust the output because "AI is smart"&lt;/td&gt;
&lt;td&gt;Verify with linters, tests, and explicit prompts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run everything through MCP&lt;/td&gt;
&lt;td&gt;Optimize for token cost and speed with CLIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use one model for everything&lt;/td&gt;
&lt;td&gt;Let Claude delegate to Codex — different bias, different blind spots&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The difference isn't the agent. The difference is the system around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI agents in infrastructure work
&lt;/h2&gt;

&lt;p&gt;But only if you build the harness first.&lt;/p&gt;

&lt;p&gt;The agent is the easy part. Any competent engineer can get Claude or GPT to generate Terraform. The hard part — the part that separates demos from production — is everything around it: the quality gates, the token optimization, the multi-model verification, the declarative infrastructure that makes it all reproducible.&lt;/p&gt;

&lt;p&gt;If you're stuck in pilot purgatory, the fix isn't a better agent. It's a better harness.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm writing more about the practitioner side of platform engineering + AI. If you're building with agents in production — not just demoing them — I'd like to hear from you.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What's your biggest blocker getting agents into production? Drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>platformengineering</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Election process using Blockchain technology</title>
      <dc:creator>Rene Zander</dc:creator>
      <pubDate>Wed, 27 Sep 2023 07:51:36 +0000</pubDate>
      <link>https://dev.to/reneza/election-process-using-blockchain-technology-4lof</link>
      <guid>https://dev.to/reneza/election-process-using-blockchain-technology-4lof</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Traditional voting systems have failed us a numerous of times in the past. Today we don’t need to make the same mistakes again, trusting in hand-counted results or waiting for days having people spend their time on work a computer could do.&lt;br&gt;&lt;br&gt;
Today we have technology that could solve most of these challenges. In Germany we have digital chips in our personal identity cards for a couple of years. Using those chips one could attempt to facilitate a vote securely for each citizen and store the record on a trusted ledger.&lt;/p&gt;

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

&lt;p&gt;The citizen has two options to vote. He can use the native desktop app with an addon or he can use the mobile app. Both applications do connect to the National voting website to authenticate the user, and assess the vote.&lt;/p&gt;

&lt;p&gt;The National voting website will forward the authenticated request to the Back office component, that will map any ID card identity to a blockchain identity. Blockchain identities are unique, similar to ID card identities.&lt;/p&gt;

&lt;p&gt;From the back office component all votes are written to the blockchain designated to contain the voting data. Each citizen is presented with the option to verify any vote himself with limited visibility. Each person's private details are protected, and cannot be accessed without proper permission. All votes written to the blockchain will be encrypted before they are written to the blockchain. Encryption is facilitated so only the government has visibility into the data.&lt;/p&gt;

&lt;p&gt;The blockchain ensures any data written to the blockchain cannot be alternated nor deleted. It only allows to add new votes. By identifying each unique user, first time of vote, and voting data the integrity of the overall voting process can be assured.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7q1gjx59vukmy3a1x6wl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7q1gjx59vukmy3a1x6wl.png" alt=" " width="670" height="641"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.ausweisapp.bund.de/sdk/desktop.html" rel="noopener noreferrer"&gt;Desktop — AusweisApp2 SDK 1.22.6 documentation (bund.de)&lt;/a&gt; &lt;a href="https://github.com/renezander030/blockvote#user-content-fnref-1-328a92f30dee4a5d0665b79d0c2bf052" rel="noopener noreferrer"&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://stackoverflow.com/questions/8750780/encrypting-data-with-a-public-key-in-node-js" rel="noopener noreferrer"&gt;Encrypting data with a public key in Node.js - Stack Overflow&lt;/a&gt; &lt;a href="https://github.com/renezander030/blockvote#user-content-fnref-2-328a92f30dee4a5d0665b79d0c2bf052" rel="noopener noreferrer"&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.waves.tech/en/building-apps/smart-contracts/writing-dapps" rel="noopener noreferrer"&gt;https://docs.waves.tech/en/building-apps/smart-contracts/writing-dapps&lt;/a&gt; &lt;a href="https://github.com/renezander030/blockvote#user-content-fnref-3-328a92f30dee4a5d0665b79d0c2bf052" rel="noopener noreferrer"&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.waves.tech/en/building-apps/smart-contracts/simple-voting-on-the-waves-blockchain#_5-voting" rel="noopener noreferrer"&gt;Simple voting on the Waves blockchain | Waves documentation&lt;/a&gt; &lt;a href="https://github.com/renezander030/blockvote#user-content-fnref-4-328a92f30dee4a5d0665b79d0c2bf052" rel="noopener noreferrer"&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/elenaili/waves8ball" rel="noopener noreferrer"&gt;GitHub - elenaili/waves8ball&lt;/a&gt; &lt;a href="https://github.com/renezander030/blockvote#user-content-fnref-5-328a92f30dee4a5d0665b79d0c2bf052" rel="noopener noreferrer"&gt;↩&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub repository &lt;a href="https://github.com/renezander030/blockvote" rel="noopener noreferrer"&gt;renezander030/blockvote: Election Process using Blockchain Technology (github.com)&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Designing a Cryptocurrency Trading Application</title>
      <dc:creator>Rene Zander</dc:creator>
      <pubDate>Mon, 14 Aug 2023 08:39:07 +0000</pubDate>
      <link>https://dev.to/reneza/designing-a-cryptocurrency-trading-application-234n</link>
      <guid>https://dev.to/reneza/designing-a-cryptocurrency-trading-application-234n</guid>
      <description>&lt;p&gt;If you’re a solution architect you likely already understand the complex nature of system design. In this post, I’ll provide a high-level overview of what’s involved in designing a cryptocurrency trading application, as well as a deep dive into the key aspects of the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Establish design scope
&lt;/h2&gt;

&lt;p&gt;First, let’s establish scope. Our goal is to create a system that can support up to 100,000 users. The app should be both, mobile and web app.&lt;/p&gt;

&lt;p&gt;Important features are discovering token swaps on a blockchain and opening positions for specific swaps. For each discovered token swap there is a wallet a user can follow.&lt;/p&gt;

&lt;p&gt;Users can create rule sets, called bots, to focus on those swaps they are most interested in. A user can follow a maximum of 100 wallets. For each wallet 100 snapshots are kept, and the total number of wallets stored is 5,000.&lt;/p&gt;

&lt;p&gt;To host the application I will leverage existing cloud hosting infrastructure. The application will run inside a container, the database will be hosted on Supabase.&lt;/p&gt;

&lt;p&gt;Now that I have outlined the requirements I can start designing the system. To fit scale constraints I use a back-of-the-envelope calculation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Queries per second (QPS)
&lt;/h2&gt;

&lt;p&gt;- Assume 100,000 users. Each user creates 10 positions per day.&lt;/p&gt;

&lt;p&gt;- QPS: 100,000 x 10 / 24 hours / 3600 seconds = ~12 queries per seconds&lt;/p&gt;

&lt;h2&gt;
  
  
  Number of servers
&lt;/h2&gt;

&lt;p&gt;- Assume one server can handle operations for 20,000 users&lt;/p&gt;

&lt;p&gt;- 100,000 users should be our scale&lt;/p&gt;

&lt;p&gt;- we need 5 servers&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage requirements
&lt;/h2&gt;

&lt;p&gt;- we store 5,000 wallets, for each wallet 100 snapshots, total of 500,000 snapshots&lt;/p&gt;

&lt;p&gt;- we store ~100 swaps x 5,000 wallets = 500,000 swaps&lt;/p&gt;

&lt;p&gt;- one wallet is copied by 10 users, resulting in positions, 5,000,000 positions&lt;/p&gt;

&lt;p&gt;- size of a position: 200 bytes&lt;/p&gt;

&lt;p&gt;- 5,000,000 x 200 bytes = 1,000,000,000 bytes = 1 GB&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Derive the high-level design
&lt;/h2&gt;

&lt;p&gt;The design is divided into two flows: swap publishing and position building. Lets explore those next.&lt;/p&gt;

&lt;p&gt;- swap publishing: when a swap event is discovered on the blockchain, corresponding data is written into cache and database. A swap is populated to the user interface component.&lt;/p&gt;

&lt;p&gt;- position building: positions are derived from swaps data, controlled by rule sets the user can create on the user interface component&lt;/p&gt;

&lt;h2&gt;
  
  
  Swap publishing
&lt;/h2&gt;

&lt;p&gt;The following figure shows the high-level design of the swap publishing flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A639%2F0%2AdqZMITdiOG-sbH1j" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A639%2F0%2AdqZMITdiOG-sbH1j" width="511" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;- Blockchain: The blockchain provides access to transactions that are written on the blockchain&lt;/p&gt;

&lt;p&gt;- Swap service: Swap service listens for swap events on the blockchain, retrieves wallet information on the swap initiator, and additional information from the related transaction&lt;/p&gt;

&lt;p&gt;- Swap cache: Swap cache holds all recent swaps. This includes all swaps that have not been processed by the position service&lt;/p&gt;

&lt;p&gt;- Swap DB: the database holds all swaps data&lt;/p&gt;

&lt;h2&gt;
  
  
  Position building
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A844%2F0%2ALtIWviHCDnhVo38P" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A844%2F0%2ALtIWviHCDnhVo38P" width="675" height="761"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;- user: user have two ways to interact with the application, mobile or web.&lt;/p&gt;

&lt;p&gt;- load balancer: the load balancer spreads incoming requests across all web servers.&lt;/p&gt;

&lt;p&gt;- web servers: web servers take incoming requests and provide access to the position service, notification service and a user interface for trade management&lt;/p&gt;

&lt;p&gt;- Position Service: Position service takes swap data from swap cache, filters for following users, and sends positions back to the blockchain using the settings a user has provided.&lt;/p&gt;

&lt;p&gt;- Position Cache: cache holds positions that are yet to be processed. Positions need to be opened, notifications are to be send&lt;/p&gt;

&lt;p&gt;- Position DB: Position DB holds all position data&lt;/p&gt;

&lt;p&gt;- Notification service: notification service sends notifications to users, i. e. via telegram&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Design deep dive
&lt;/h2&gt;

&lt;p&gt;The high-level design briefly covered two flows: swap publishing, and position building. Here, we discuss those topics in more depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Swap publishing deep dive
&lt;/h2&gt;

&lt;p&gt;Figure to show detailed design:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A701%2F0%2ABNqbmTL_W1DqTZks" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A701%2F0%2ABNqbmTL_W1DqTZks" width="561" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We touched on the basic process how swap publishing works. Let’s explore more in-depth.&lt;/p&gt;

&lt;p&gt;1. Connect to a Web 3 API provider: The application will connect to a Web 3 API provider to access the blockchain, and start to listen for swap events on the US dollar stablecoin token contract (in blockchain land called Tether): The application willl specifically listen for swap events on the Tether token contract, as this is a common stablecoin used in cryptocurrency trading.&lt;/p&gt;

&lt;p&gt;2. Further the swap sender’s token balances and related transactions will be retrieved: Once a swap event is detected, the sender’s token balances and related transactions are retrieved, getting all that is needed to build another position. All this information is written to cache. Beside the swap data there is also a snapshot of the sender’s wallet being recorded, documenting the amount of tokens at the time: Every time a swap of tokens is discovered on a transfer event a snapshot of the senders wallet is taken. Once the initial snapshot exists the app can start calculating profits for all tokens the time the next snapshot has been written to the database.&lt;/p&gt;

&lt;p&gt;3. Write the swaps to the database: Finally, swaps are written to the database for further processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web servers
&lt;/h2&gt;

&lt;p&gt;Web servers take requests from the load balancer and provide access to APIs, and the user interface. Also, web servers control rate limiting, and handle authentication.&lt;/p&gt;

&lt;p&gt;Authentication is needed to provide access, and allow to allocate data a user has created to his account.&lt;/p&gt;

&lt;p&gt;Rate limiting is essential to the health of the application, and block bad actors from misuse. The application provides several APIs, that are in scope for rate limiting. The implementation sits on the web server tier, basicly intercepting requests as a middleware. There are different algorithms to choose from. For this application we use the token bucket algorithm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Position building deep dive
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A875%2F0%2A69OR8VkXJdEx_dX7" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A875%2F0%2A69OR8VkXJdEx_dX7" width="719" height="761"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is how position building works:&lt;/p&gt;

&lt;p&gt;To allow users open positions they would need to set up a trading account on the user interface. Once they have a wallet, they start funding it, and configure the trading experience to their liking.&lt;/p&gt;

&lt;p&gt;1. The position service listens for new swaps on the cache tier. Inserted swaps are broadcasted to allow the creation of positions from the swaps data.&lt;/p&gt;

&lt;p&gt;2. Every swap could be a potential position. Users who do follow a wallet related to the swap have a position being initialized and send back to the blockchain.&lt;/p&gt;

&lt;p&gt;3. Notifications are sent out through external service, Telegram Messenger. Before using the service a user would contact the application’s Telegram Bot, retrieve an ID they would connect with their user account in the profile section on the user interface.&lt;/p&gt;

&lt;p&gt;4. Positions are shown on the user interface. The user interface allows users to discover wallets they might want to follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache
&lt;/h2&gt;

&lt;p&gt;A cache is a temporary storage area that stores the result of expensive responses or frequently accessed data in memory. The application performance is greatly affected by calling the database repeatedly. The cache can mitigate this problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache tier
&lt;/h2&gt;

&lt;p&gt;The cache tier is a temporary data store layer, much faster than the database. The following figure shows the setup of a cache server:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A701%2F0%2AVNjcV0_Trfn8EWUC" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A701%2F0%2AVNjcV0_Trfn8EWUC" width="561" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After receiving a request, a web server first checks if the cache has the available response. If it has, it sends data back to the client. If not, it queries the database, stores the response in cache, and sends it back to the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache architecture
&lt;/h2&gt;

&lt;p&gt;Cache does enhance the performance of the application. We divide the cache tier into 4 layers as shown in the following figure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A589%2F0%2AfsgiFXW5O4Mx-dW0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afit%3A589%2F0%2AfsgiFXW5O4Mx-dW0" width="471" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;- Swap data: it stores information about the most recent wallet snapshots and swaps&lt;/p&gt;

&lt;p&gt;- Social Graph: stores relationships between users, bots, and wallets&lt;/p&gt;

&lt;p&gt;- Trading: stores information about positions&lt;/p&gt;

&lt;p&gt;- Counters: stores counts for follows and positions&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Wrap up
&lt;/h2&gt;

&lt;p&gt;In this post, we designed a cryptocurrency trading application. We followed along the process of scoping the requirements, deriving a high level design, and dived in more deeply into the core components of the application.&lt;/p&gt;

&lt;p&gt;This design is not perfect. It is always important to know what the requirements are, what is in scope, and to iterate. You only know so much when you start out. Once you revisit a system after some time requirements might have changed, scaling contraints might be different, or the importance of features has changed.&lt;/p&gt;

&lt;p&gt;Here are a few ideas to follow up on this design:&lt;/p&gt;

&lt;p&gt;- replace postgres with a graphdb for more performance&lt;/p&gt;

&lt;p&gt;- build out a module system and integrate with a larger system like Dune.com&lt;/p&gt;

&lt;p&gt;- rebuild the app as a monolith to reduce latency between components&lt;/p&gt;

&lt;p&gt;- rebuild to support 100M users&lt;/p&gt;

&lt;p&gt;I hope you enjoyed reading this article, and learned something. ;-)&lt;/p&gt;

&lt;p&gt;Please consider following me. I plan to post more content on system design and related topics.🥳🥳&lt;/p&gt;

&lt;p&gt;René&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference materials
&lt;/h2&gt;

&lt;p&gt;1. Demo application &lt;a href="https://ramaris.app/" rel="noopener noreferrer"&gt;https://ramaris.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2. Code Base &lt;a href="https://github.com/renezander030/ramaris" rel="noopener noreferrer"&gt;https://github.com/renezander030/ramaris&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3. Let’s talk &lt;a href="https://www.linkedin.com/in/reneza" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/reneza&lt;/a&gt;&lt;/p&gt;

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