<?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>Forem: Benjamin Cane</title>
    <description>The latest articles on Forem by Benjamin Cane (@madflojo).</description>
    <link>https://forem.com/madflojo</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%2F2573285%2F844e50df-c3e8-456f-a257-020f7711bb97.png</url>
      <title>Forem: Benjamin Cane</title>
      <link>https://forem.com/madflojo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/madflojo"/>
    <language>en</language>
    <item>
      <title>Deterministic routing is one of the most effective ways distributed systems reduce consistency problems at scale</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 01 May 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/deterministic-routing-is-one-of-the-most-effective-ways-distributed-systems-reduce-consistency-3bm</link>
      <guid>https://forem.com/madflojo/deterministic-routing-is-one-of-the-most-effective-ways-distributed-systems-reduce-consistency-3bm</guid>
      <description>&lt;p&gt;Deterministic routing is one of the most effective ways distributed systems reduce consistency problems at scale.&lt;/p&gt;

&lt;p&gt;It is a foundational technique used by many modern databases, caches, and large-scale platforms. Understand how it works and you can apply the same pattern in your own systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 Understanding the Problem
&lt;/h2&gt;

&lt;p&gt;At some point, every successful system hits the limits of a single database instance.&lt;/p&gt;

&lt;p&gt;A single server can only handle so many connections, queries, writes, storage capacity, or CPU/memory demands. Even with the best hardware, performance eventually degrades. So systems scale horizontally.&lt;/p&gt;

&lt;p&gt;Instead of sending all traffic to a single database server, requests are distributed across multiple nodes.&lt;/p&gt;

&lt;p&gt;At the same time, resiliency matters. If one server fails and all data resides there, the outage can be severe.&lt;/p&gt;

&lt;p&gt;So modern databases spread data across multiple nodes, availability zones, and regions.&lt;/p&gt;

&lt;p&gt;Distributing load and data solves both capacity and resiliency problems. But it introduces another challenge.&lt;/p&gt;

&lt;p&gt;How do you keep request behavior consistent when data is distributed across multiple systems?&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ Why Replication Is Not Enough
&lt;/h2&gt;

&lt;p&gt;Replication helps, but it does not solve every consistency problem.&lt;/p&gt;

&lt;p&gt;Imagine a write lands on Server 1. Immediately after, a read request for the same data lands on Server 67. Will Server 67 have the latest version? Maybe, but often not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Asynchronous Replication
&lt;/h3&gt;

&lt;p&gt;With asynchronous replication, Server 1 will accept the write and replicate the data to other servers in the background. That means a follow-up read on any other node may return stale data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Synchronous Replication
&lt;/h3&gt;

&lt;p&gt;With synchronous replication, the write on Server 1 will wait for an acknowledgment from all replicas before returning a success. While this improves consistency guarantees, it increases latency.&lt;/p&gt;

&lt;p&gt;The farther apart a replica is, the worse this gets. Local writes may be fast, but cross-region writes will be slow. Plus, is it really feasible to replicate data across every single node?&lt;/p&gt;

&lt;p&gt;So the question becomes: &lt;em&gt;How do you preserve consistency, without paying latency taxes?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔀 Route Requests to the Data
&lt;/h2&gt;

&lt;p&gt;A highly effective answer is deterministic routing.&lt;/p&gt;

&lt;p&gt;Instead of moving data to where requests might land, move requests to where the data already exists.&lt;/p&gt;

&lt;p&gt;If requests for the same key can go to the same node, you gain predictable ownership, reduced stale reads, lower coordination overhead, and easier horizontal scaling.&lt;/p&gt;

&lt;h2&gt;
  
  
  👨‍🏫 How Deterministic Routing Works
&lt;/h2&gt;

&lt;p&gt;At a high level, the system needs a repeatable way to decide where requests should go.&lt;/p&gt;

&lt;p&gt;A common approach is hashing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A hash of &lt;code&gt;user123&lt;/code&gt; always goes to Node 7&lt;/li&gt;
&lt;li&gt;A hash of &lt;code&gt;user456&lt;/code&gt; always goes to Node 42&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As long as the same key produces the same result, requests can be consistently routed to the same owner. Many modern databases implement deterministic routing through techniques like consistent hashing, partition maps, and shard ranges.&lt;/p&gt;

&lt;h2&gt;
  
  
  🗺️ Where Routing Logic Lives
&lt;/h2&gt;

&lt;p&gt;Different systems solve routing in different places.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client-side Routing
&lt;/h3&gt;

&lt;p&gt;The client library knows the partition map and sends requests directly to the correct node. Used by many distributed caches and databases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proxy / Router Tier
&lt;/h3&gt;

&lt;p&gt;A small router sits in front of nodes and forwards traffic appropriately. Useful when client behavior cannot be influenced.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server-side Forwarding
&lt;/h3&gt;

&lt;p&gt;Requests land anywhere, and the receiving node forwards internally to the owning node. Simple for clients, doesn’t introduce a proxy failure point, but introduces complex cluster discovery/health monitoring.&lt;/p&gt;

&lt;p&gt;Each model has tradeoffs.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧰 Routing Does Not Replace Replication
&lt;/h2&gt;

&lt;p&gt;Deterministic routing is powerful, but not magic. What happens when the owning node is down? You still need replication.&lt;/p&gt;

&lt;p&gt;Modern databases combine both: deterministic routing for performance and ownership, plus replication for durability and failover.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Why This Matters Beyond Databases
&lt;/h2&gt;

&lt;p&gt;Distributed databases use this approach, but it is not unique to them.&lt;/p&gt;

&lt;p&gt;Deterministic routing can be used to solve: session ownership, user affinity, in-memory workflow coordination, work queue partitioning, and more.&lt;/p&gt;

&lt;p&gt;I’ve used deterministic routing many times to solve load distribution and consistency problems.&lt;/p&gt;

&lt;p&gt;At scale, the answer is not always more/better hardware. Consistency and availability problems are not always solved with replication alone.&lt;/p&gt;

&lt;p&gt;Sometimes the best answer is simply to send the request to the right place.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>database</category>
      <category>distributedsystems</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>When you think of microservices, you probably think of centralized shared services. But there's another valid pattern that is...</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/when-you-think-of-microservices-you-probably-think-of-centralized-shared-services-but-theres-16l5</link>
      <guid>https://forem.com/madflojo/when-you-think-of-microservices-you-probably-think-of-centralized-shared-services-but-theres-16l5</guid>
      <description>&lt;p&gt;When you think of microservices, you probably think of centralized shared services. But there’s another valid pattern that is rarely discussed: running the same microservice inside multiple platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 How It Usually Works
&lt;/h2&gt;

&lt;p&gt;Most microservice designs follow the same model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Break systems into capabilities, teams, or functions&lt;/li&gt;
&lt;li&gt;Deploy one shared service for each capability&lt;/li&gt;
&lt;li&gt;Any platform that needs it calls that centralized service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That works well for many cases, but it’s not the only model.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏗️ How We Got Here
&lt;/h2&gt;

&lt;p&gt;Before microservices, many organizations used Service-Oriented Architecture (SOA).&lt;/p&gt;

&lt;p&gt;Despite being labeled as antiquated, SOA and microservices are not that different. Both break down systems into capabilities that communicate with each other. The biggest difference is scope.&lt;/p&gt;

&lt;p&gt;In SOA, a “Payments Service” might own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Message parsing&lt;/li&gt;
&lt;li&gt;Validation&lt;/li&gt;
&lt;li&gt;Balance checks&lt;/li&gt;
&lt;li&gt;Currency conversion&lt;/li&gt;
&lt;li&gt;Settlement logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While other SOA services would own “Users” or “Accounting”. Today, that payment service would be considered an entire platform, with each of those capabilities implemented as microservices within that domain.&lt;/p&gt;

&lt;p&gt;Microservices are often the same idea as SOA, just at a more granular level.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Why Centralization Became the Default
&lt;/h2&gt;

&lt;p&gt;One reason microservices gained traction was the need to avoid duplication. Capabilities were often rebuilt across multiple systems. For example, Currency Conversion is needed in Payments, Accounting, and many other platforms.&lt;/p&gt;

&lt;p&gt;Duplication is not just wasteful, it creates real problems: logic drift, coordination overhead, and inconsistent outcomes across systems. Packaging that capability as a standalone service solved real problems: build once, reuse everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ The Downside of Centralization
&lt;/h2&gt;

&lt;p&gt;In cell-based architectures, platforms are usually designed to be self-contained and failure-isolated. That means a mission-critical platform depending on a centralized service shared by other platforms can become a design smell.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cross-cell dependencies&lt;/li&gt;
&lt;li&gt;Added latency&lt;/li&gt;
&lt;li&gt;Shared failure domains&lt;/li&gt;
&lt;li&gt;Complex failover scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So teams, once again, solve these problems by rebuilding the same capability locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔁 Another Option
&lt;/h2&gt;

&lt;p&gt;Instead of rebuilding the capability each time, deploy the same microservice codebase inside multiple platforms. If both Payments and Accounting need a currency conversion service, deploy the same service within each platform.&lt;/p&gt;

&lt;p&gt;It’s the same codebase and capability, but with local ownership and resilience. You get reuse without forced centralization.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Caveats from Experience
&lt;/h2&gt;

&lt;p&gt;This pattern works when applied carefully.&lt;/p&gt;

&lt;h3&gt;
  
  
  1️⃣ Strong Ownership
&lt;/h3&gt;

&lt;p&gt;A shared codebase still needs a clear owning team. Others can contribute, but someone must own quality, roadmap, and releases.&lt;/p&gt;

&lt;h3&gt;
  
  
  2️⃣ Pick the Right Capabilities
&lt;/h3&gt;

&lt;p&gt;Not everything is a great fit. Something like currency conversion is well-scoped, relatively stateless, and doesn’t have unique business logic based on which platform is calling it. It’s a strong example.&lt;/p&gt;

&lt;p&gt;But other services that have unique logic for each platform domain or require consistency across different platforms are less of a fit.&lt;/p&gt;

&lt;h3&gt;
  
  
  3️⃣ Operational Discipline
&lt;/h3&gt;

&lt;p&gt;Using the same codebase doesn’t automatically solve all problems; you can still run into drift across platforms if each is running a different version. Changes in behavior still sometimes need coordination.&lt;/p&gt;

&lt;p&gt;But with a single codebase, these issues are far easier to address.&lt;/p&gt;

&lt;h2&gt;
  
  
  💭 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Microservices gave us reusable building blocks. Sometimes the best use of a microservice is not one centralized deployment. Sometimes it’s many local deployments of the same capability.&lt;/p&gt;

&lt;p&gt;Just reuse the software while maintaining autonomy.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Are you using traffic mirroring in production? If not, try it out.</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 17 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/are-you-using-traffic-mirroring-in-production-if-not-try-it-out-iek</link>
      <guid>https://forem.com/madflojo/are-you-using-traffic-mirroring-in-production-if-not-try-it-out-iek</guid>
      <description>&lt;p&gt;Are you using traffic mirroring in production? If not, you might be missing one of the safest ways to test and observe production changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚦 What is Traffic Mirroring?
&lt;/h2&gt;

&lt;p&gt;Traffic mirroring in &lt;code&gt;Istio&lt;/code&gt; or &lt;code&gt;Envoy Proxy&lt;/code&gt; lets you send a copy of live traffic to a secondary target.&lt;/p&gt;

&lt;p&gt;When enabled, traffic to &lt;code&gt;/service&lt;/code&gt; routes to &lt;code&gt;cluster1&lt;/code&gt; as normal, and a mirrored copy is sent to &lt;code&gt;cluster2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key:&lt;/strong&gt; mirrored traffic is fire-and-forget. Responses are ignored and never impact the primary request.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Why It’s Powerful
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ Shadow Traffic for Safe Testing
&lt;/h3&gt;

&lt;p&gt;The most common use case is shadow traffic.&lt;/p&gt;

&lt;p&gt;When migrating platforms or deploying a new version of an application, you can send real traffic to the new system, observe behavior, and validate responses.&lt;/p&gt;

&lt;p&gt;All without impacting users. No risky cutovers. You see exactly how the new system behaves under real load.&lt;/p&gt;

&lt;h3&gt;
  
  
  2️⃣ Out-of-Band Traffic Inspection
&lt;/h3&gt;

&lt;p&gt;Another powerful use case is traffic inspection.&lt;/p&gt;

&lt;p&gt;Inline inspection is risky. It adds latency, introduces new failure points, and becomes part of the critical path.&lt;/p&gt;

&lt;p&gt;With traffic mirroring, you can inspect traffic, analyze requests, and detect anomalies.&lt;/p&gt;

&lt;p&gt;All without impacting the primary path.&lt;/p&gt;

&lt;h2&gt;
  
  
  😶‍🌫️ Reality Check
&lt;/h2&gt;

&lt;p&gt;It’s not perfect. There is some overhead.&lt;/p&gt;

&lt;p&gt;Mirroring adds load to the sidecar, which may or may not be acceptable for your system. In my experience, it’s negligible, but it’s something you should measure in your own environment before deploying to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Traffic mirroring is one of the safest ways to validate migrations, test new systems, and observe real production behavior.&lt;/p&gt;

&lt;p&gt;The hard part isn’t mirroring traffic. It’s running two production systems in parallel. That’s the real cost, and the real tradeoff.&lt;/p&gt;

&lt;p&gt;But if you can afford that cost, traffic mirroring is an incredibly powerful tool.&lt;/p&gt;

&lt;p&gt;If you want to dig deeper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://istio.io/latest/docs/tasks/traffic-management/mirroring/" rel="noopener noreferrer"&gt;Istio traffic mirroring docs&lt;/a&gt; explain the workflow.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-routeaction-requestmirrorpolicy" rel="noopener noreferrer"&gt;Envoy request mirror policy docs&lt;/a&gt; cover the lower-level routing behavior.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>networking</category>
      <category>sre</category>
      <category>testing</category>
    </item>
    <item>
      <title>Agent Skills Are Becoming the Best Way to Capture Institutional Knowledge</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/agent-skills-are-becoming-the-best-way-to-capture-institutional-knowledge-122d</link>
      <guid>https://forem.com/madflojo/agent-skills-are-becoming-the-best-way-to-capture-institutional-knowledge-122d</guid>
      <description>&lt;p&gt;Use Agent Skills to capture institutional knowledge and make it usable by coding agents.&lt;/p&gt;

&lt;p&gt;Every organization has institutional knowledge.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal frameworks&lt;/li&gt;
&lt;li&gt;Preferred practices&lt;/li&gt;
&lt;li&gt;Platform-specific capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It exists everywhere. But it’s often undocumented… or buried in a wiki no one reads.&lt;/p&gt;

&lt;p&gt;As coding agents take on more work, this problem gets worse.&lt;/p&gt;

&lt;p&gt;If you ask an agent to build a new service, you want it to use your internal framework, follow your patterns, and respect your organizational constraints.&lt;/p&gt;

&lt;p&gt;A human engineer would ask questions. An agent won’t, unless you give it that context.&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Agent Skills as Knowledge Distribution
&lt;/h2&gt;

&lt;p&gt;Most people think about Agent Skills as actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert markdown to PDF&lt;/li&gt;
&lt;li&gt;Review this pull request&lt;/li&gt;
&lt;li&gt;Commit my changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the more interesting use case is guidance.&lt;/p&gt;

&lt;p&gt;Skills aren’t just for doing things. They’re for shaping agent output.&lt;/p&gt;

&lt;p&gt;Agents discover and use skills based on intent.&lt;/p&gt;

&lt;p&gt;If a user asks: “Create a new Python service.”&lt;/p&gt;

&lt;p&gt;The agent looks for relevant skills:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Language conventions (PEP 8, etc.)&lt;/li&gt;
&lt;li&gt;Internal frameworks&lt;/li&gt;
&lt;li&gt;Organizational standards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s where institutional knowledge belongs.&lt;/p&gt;

&lt;p&gt;Instead of hoping engineers remember to tell the agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“We use Flask, not Django.”&lt;/li&gt;
&lt;li&gt;“Stick to the standard library.”&lt;/li&gt;
&lt;li&gt;“Follow this service layout.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You capture that into a skill. The agent applies it automatically.&lt;/p&gt;

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

&lt;p&gt;Institutional knowledge only works if it's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discoverable&lt;/li&gt;
&lt;li&gt;Applied consistently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agent Skills give you both.&lt;/p&gt;

&lt;p&gt;They turn tribal knowledge into something agents can find, understand, and use.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ The Tradeoff (For Now)
&lt;/h2&gt;

&lt;p&gt;Right now, this introduces duplication.&lt;/p&gt;

&lt;p&gt;Most teams already have internal docs, style guides, &amp;amp; wikis.&lt;/p&gt;

&lt;p&gt;And now you’re putting the same information into skills. Which feels like extra work.&lt;/p&gt;

&lt;p&gt;But it poses an interesting question:&lt;/p&gt;

&lt;p&gt;As agents become the primary interface… Will engineers read the wiki? Or ask the agent?&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;As agents take on more of the implementation work, where you store knowledge becomes more important. Making that knowledge accessible to agents becomes essential.&lt;/p&gt;

&lt;p&gt;Agent Skills aren’t just automation tools.&lt;/p&gt;

&lt;p&gt;They are becoming the interface for standards, practices, and institutional knowledge.&lt;/p&gt;

&lt;p&gt;And teams that embrace that early will see more consistent output from both humans and agents.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>documentation</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Saved Prompts Are Dead. Agent Skills Are the Future.</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 03 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/saved-prompts-are-dead-agent-skills-are-the-future-13kk</link>
      <guid>https://forem.com/madflojo/saved-prompts-are-dead-agent-skills-are-the-future-13kk</guid>
      <description>&lt;p&gt;Saved prompts are dead. Agent Skills are the next step.&lt;/p&gt;

&lt;p&gt;If you’ve been around for a while, you probably have a file full of bash one-liners.&lt;/p&gt;

&lt;p&gt;Small scripts or commands you saved because they solved a problem you didn’t want to automate properly.&lt;/p&gt;

&lt;p&gt;When coding agents arrived, prompts became the new one-liners.&lt;/p&gt;

&lt;p&gt;Useful prompts were saved, reused, and eventually turned into “prompt files”, then slash commands like &lt;code&gt;/do-something&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But that model has already evolved.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Agent Skills
&lt;/h2&gt;

&lt;p&gt;Agent Skills are the next iteration.&lt;/p&gt;

&lt;p&gt;At a basic level, a skill looks a lot like a saved prompt: a directory with a markdown file.&lt;/p&gt;

&lt;p&gt;What makes it different is how it’s used.&lt;/p&gt;

&lt;p&gt;Skills include metadata like name and description, allowing agents to discover them.&lt;/p&gt;

&lt;p&gt;Instead of explicitly calling a prompt every time, the agent can determine when to use a skill based on intent.&lt;/p&gt;

&lt;p&gt;This is referred to as progressive disclosure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agent loads skill metadata&lt;/li&gt;
&lt;li&gt;Matches it to your task&lt;/li&gt;
&lt;li&gt;Then loads and executes the full skill when needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can still call skills directly (&lt;code&gt;/&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, &lt;code&gt;@&lt;/code&gt;), but you don’t always have to.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 More Than Just Prompts
&lt;/h2&gt;

&lt;p&gt;The real differentiator is that skills aren’t just prompts.&lt;/p&gt;

&lt;p&gt;They can include reference documentation, templates, and scripts.&lt;/p&gt;

&lt;p&gt;This means you’re no longer just telling the agent what to do.&lt;/p&gt;

&lt;p&gt;You’re giving it tools and context to execute and validate tasks.&lt;/p&gt;

&lt;p&gt;For more complex workflows, it’s often easier to write a script and teach the agent how to use it than to encode everything in a prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ A Word of Caution
&lt;/h2&gt;

&lt;p&gt;This power comes with risk.&lt;/p&gt;

&lt;p&gt;Skills can include executable logic and tell agents to perform tasks.&lt;/p&gt;

&lt;p&gt;That means a shared skill can contain malicious or unsafe behavior.&lt;/p&gt;

&lt;p&gt;Treat them like any script you install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand what they do&lt;/li&gt;
&lt;li&gt;Know where they come from&lt;/li&gt;
&lt;li&gt;Review before using (watch out for hidden text or obfuscated instructions)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Agent skills are a meaningful step forward.&lt;/p&gt;

&lt;p&gt;They let you codify workflows, preferences, and repeatable agent tasks in a way that agents can discover.&lt;/p&gt;

&lt;p&gt;They’re a strong productivity accelerator and a powerful way to capture institutional knowledge in a form agents can actually use.&lt;/p&gt;

&lt;p&gt;(More on that in the next post.)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Generating Code Faster Is Only Valuable If You Can Validate Every Change With Confidence</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 27 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/generating-code-faster-is-only-valuable-if-you-can-validate-every-change-with-confidence-3fe3</link>
      <guid>https://forem.com/madflojo/generating-code-faster-is-only-valuable-if-you-can-validate-every-change-with-confidence-3fe3</guid>
      <description>&lt;p&gt;Generating code faster is only valuable if you can validate every change with confidence.&lt;/p&gt;

&lt;p&gt;Software engineering has never really been about writing code. Coding is often the easy part.&lt;/p&gt;

&lt;p&gt;Testing is harder, and many teams struggle with it.&lt;/p&gt;

&lt;p&gt;As tools make it easier to generate code quickly, that gap widens. If you can produce changes faster than you can validate them, you eventually create more code than you can safely operate.&lt;/p&gt;

&lt;p&gt;Which begs the question: What does good testing actually look like?&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 What Good Looks Like
&lt;/h2&gt;

&lt;p&gt;One of the biggest challenges I see is that teams struggle to understand what “good” testing means and never define it.&lt;/p&gt;

&lt;p&gt;Pipelines are often built early in a project, when the team is small, and they rarely keep pace with the system and organization as they grow.&lt;/p&gt;

&lt;p&gt;My starting principle is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;At pull request time, you should have strong confidence that the change will not break the service or platform being modified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Within a day of merging, you should have strong confidence that the change hasn’t broken the full customer journey that the platform supports.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔁 On Pull Request
&lt;/h2&gt;

&lt;p&gt;For backend platforms, I like to see three levels of automated testing before merging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Tests (Unit Tests)
&lt;/h3&gt;

&lt;p&gt;This level is the foundation. Unit tests validate internal logic, error handling, and edge cases. Techniques such as fuzz testing and benchmarking also reveal issues early. As the test pyramid tells us, this is where the majority of testing and logic validation should take place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service-Level Functional Tests
&lt;/h3&gt;

&lt;p&gt;Too many teams stop at unit tests for pull requests. Functional tests should also be run in CI for every pull request.&lt;/p&gt;

&lt;p&gt;Services should be tested in isolation with functional tests. Dependencies can be mocked, but things like databases should ideally run for real (Dockerized).&lt;/p&gt;

&lt;p&gt;This is where API contracts are validated and regressions can be identified without wondering whether the issue came from this change or another service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Platform-Level Functional Tests
&lt;/h3&gt;

&lt;p&gt;Testing a service alone isn’t enough. Changes can break upstream or downstream dependencies. Platform-level tests spin up the entire platform in CI and validate that services interact correctly.&lt;/p&gt;

&lt;p&gt;These tests ensure the platform continues to work as a system.&lt;/p&gt;

&lt;p&gt;For platforms with strict latency or resiliency requirements, I recommend introducing light stress tests at both the service and platform levels. These aren’t full performance tests, but they act as early indicators of performance regressions.&lt;/p&gt;

&lt;p&gt;If these three layers pass, you should have high confidence in the change. But not complete confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌙 Nightly Testing
&lt;/h2&gt;

&lt;p&gt;Some failures take time to appear.&lt;/p&gt;

&lt;p&gt;Memory leaks, performance degradation, and cross-platform integration issues may not show up immediately.&lt;/p&gt;

&lt;p&gt;That’s why I like to run a nightly build (or every few hours).&lt;/p&gt;

&lt;p&gt;This environment runs end-to-end customer journey tests, performance tests, and chaos tests.&lt;/p&gt;

&lt;p&gt;These are typically the same tests used during release validation, but running them continuously accelerates feedback. If something breaks, you learn about it early, before the pressure of a release.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;There is no universal approach everyone can follow.&lt;/p&gt;

&lt;p&gt;Different systems have different needs; mission-critical systems may focus heavily on correctness and resilience. Non-mission-critical systems may focus more on validating core functionality.&lt;/p&gt;

&lt;p&gt;Your testing strategy depends heavily on architecture, dependencies, and operational constraints. But if your organization is increasing its ability to generate code quickly, your testing capabilities must evolve at the same pace.&lt;/p&gt;

&lt;p&gt;AI-generated code becomes much easier to review when you already have high confidence in your testing.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>testing</category>
    </item>
    <item>
      <title>When You Go to Production with gRPC, Make Sure You’ve Solved Load Distribution First</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 20 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/when-you-go-to-production-with-grpc-make-sure-youve-solved-load-distribution-first-30f8</link>
      <guid>https://forem.com/madflojo/when-you-go-to-production-with-grpc-make-sure-youve-solved-load-distribution-first-30f8</guid>
      <description>&lt;p&gt;When you go to production with gRPC, make sure you’ve solved load distribution first.&lt;/p&gt;

&lt;p&gt;I was recently talking with another engineer who is rolling out gRPC into production. He asked what the biggest gotchas were.&lt;/p&gt;

&lt;p&gt;My first answer: Load Distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚦 HTTP/1 vs. HTTP/2
&lt;/h2&gt;

&lt;p&gt;Most teams first implement services using REST over HTTP/1 and then migrate to gRPC as they seek its performance benefits.&lt;/p&gt;

&lt;p&gt;That shift introduces a subtle but important change in how traffic gets distributed across instances.&lt;/p&gt;

&lt;p&gt;With HTTP/1, requests are generally tied closely to connections. A client opens a connection, sends a request, waits for the response, and then sends another (if connection re-use is enabled).&lt;/p&gt;

&lt;p&gt;HTTP/2 (which underpins gRPC) works differently.&lt;/p&gt;

&lt;p&gt;HTTP/2 multiplexes requests over persistent connections. A client can send many requests over the same connection without waiting for responses.&lt;/p&gt;

&lt;p&gt;This is one of the reasons gRPC provides a performance boost, but it can create unexpected load distribution issues.&lt;/p&gt;

&lt;p&gt;If your infrastructure isn’t built for an HTTP/2 world, you’ll quickly find traffic becoming unevenly distributed.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏗️ Infrastructure Support
&lt;/h2&gt;

&lt;p&gt;In an HTTP/1 world, load balancing at the connection (Layer 4) level often works well enough. But with HTTP/2, connections live much longer and carry far more concurrent traffic.&lt;/p&gt;

&lt;p&gt;If your load balancer distributes traffic based only on connections, a busy client may hammer a single instance while others sit idle.&lt;/p&gt;

&lt;p&gt;Unfortunately, much of the infrastructure still doesn’t fully support HTTP/2-aware load balancing.&lt;/p&gt;

&lt;p&gt;Depending on your environment, your load balancers or ingress controllers may operate primarily at Layer 4. That works fine for HTTP/1, but once you introduce HTTP/2 via gRPC, the effectiveness changes significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Supporting gRPC
&lt;/h2&gt;

&lt;p&gt;To get the most out of gRPC, the best approach is to use infrastructure that understands HTTP/2 and load-balances requests rather than just connections.&lt;/p&gt;

&lt;p&gt;If that’s not possible, another option is client-side load balancing.&lt;/p&gt;

&lt;p&gt;Many gRPC clients support opening a pool of connections and distributing requests across them. You still benefit from HTTP/2’s persistent connections, but you avoid concentrating all traffic on a single backend instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;gRPC offers many advantages, including performance, strongly typed contracts, and efficient communication. But it also introduces different networking behavior.&lt;/p&gt;

&lt;p&gt;If you’re rolling out gRPC into production, make sure your load balancing infrastructure is ready for an HTTP/2 world.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>distributedsystems</category>
      <category>networking</category>
    </item>
    <item>
      <title>You may be building for availability, but are you building for resiliency?</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 13 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/you-may-be-building-for-availability-but-are-you-building-for-resiliency-34om</link>
      <guid>https://forem.com/madflojo/you-may-be-building-for-availability-but-are-you-building-for-resiliency-34om</guid>
      <description>&lt;p&gt;You may be building for availability, but are you building for resiliency? Many teams design for availability. Far fewer design for resiliency.&lt;/p&gt;

&lt;p&gt;A concept that took me a while to really grasp is that building highly available systems and highly resilient systems is not the same thing.&lt;/p&gt;

&lt;p&gt;The difference is how the system reacts to failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚄 High Availability
&lt;/h2&gt;

&lt;p&gt;When you build for high availability, the goal is simple: ensure there is always another path.&lt;/p&gt;

&lt;p&gt;If something fails, traffic can be redirected somewhere else.&lt;/p&gt;

&lt;p&gt;For example, a service might run across multiple availability zones or regions. If one fails, traffic is routed to another.&lt;/p&gt;

&lt;p&gt;Detecting failures and redirecting traffic are core elements of building for high availability.&lt;/p&gt;

&lt;p&gt;Availability is about rerouting traffic when something fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚂 High Resiliency
&lt;/h2&gt;

&lt;p&gt;Building for resiliency is different.&lt;/p&gt;

&lt;p&gt;The solution to failure isn’t another path; it’s how the system handles the error.&lt;/p&gt;

&lt;p&gt;When a dependency fails, the decision becomes:&lt;/p&gt;

&lt;p&gt;Do we retry? Do we continue without that dependency? Do we degrade functionality? Do we stop processing altogether?&lt;/p&gt;

&lt;p&gt;Resiliency is about defining what happens when things go wrong.&lt;/p&gt;

&lt;p&gt;Sometimes you can continue processing. Sometimes you can defer work and fix it later.&lt;/p&gt;

&lt;p&gt;Resiliency is absorbing failure instead of avoiding it.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 A Simple Example
&lt;/h2&gt;

&lt;p&gt;When you design systems with resiliency in mind, you tend to treat dependencies differently.&lt;/p&gt;

&lt;p&gt;A simple example is configuration.&lt;/p&gt;

&lt;p&gt;Many systems use distributed configuration services so that runtime behavior can change without redeployment.&lt;/p&gt;

&lt;p&gt;But that configuration service then becomes a dependency. To avoid turning it into a hard dependency, many systems cache the configuration in memory.&lt;/p&gt;

&lt;p&gt;When updates occur, the system fetches the new configuration and switches only after it’s fully loaded into memory.&lt;/p&gt;

&lt;p&gt;If configuration refresh fails, the system continues operating with the last known configuration. Transient failures don’t bring the system down.&lt;/p&gt;

&lt;p&gt;That’s resiliency.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;When I talk about non-functional requirements, you’ll hear me say:&lt;/p&gt;

&lt;p&gt;“Highly available and resilient systems”&lt;/p&gt;

&lt;p&gt;I separate them intentionally because the approaches are different.&lt;/p&gt;

&lt;p&gt;Availability ensures there is always another path. Resiliency ensures the system can continue operating when failures occur.&lt;/p&gt;

&lt;p&gt;Availability routes around failure. Resiliency survives failure. You need both.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>distributedsystems</category>
      <category>sre</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>When your coding agent doesn’t understand your project, you’ll get junk</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 06 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/when-your-coding-agent-doesnt-understand-your-project-youll-get-junk-8b2</link>
      <guid>https://forem.com/madflojo/when-your-coding-agent-doesnt-understand-your-project-youll-get-junk-8b2</guid>
      <description>&lt;p&gt;When your coding agent doesn’t understand your project, you’ll get junk.&lt;/p&gt;

&lt;p&gt;Junk in, junk out.&lt;/p&gt;

&lt;p&gt;One of the best ways to get more from agentic coding tools is to give the agent context.&lt;/p&gt;

&lt;p&gt;The more an agent understands your project, the better its work will be.&lt;/p&gt;

&lt;p&gt;If you ask an agent to add a method to a class, it will. It might read the file. It might infer some structure. But it won’t understand the project's intent.&lt;/p&gt;

&lt;p&gt;If you asked a human engineer to make the same change, they would have questions.&lt;/p&gt;

&lt;p&gt;What is the purpose of this project? How is it used? What constraints exist?&lt;/p&gt;

&lt;p&gt;If they skipped that step, you’d get exactly what you asked for, even if it was wrong.&lt;/p&gt;

&lt;p&gt;That’s the same challenge many face with coding agents. A lack of context means it only does what it’s told — which isn’t always what you actually need.&lt;/p&gt;

&lt;p&gt;But when it understands a project, it operates with far more clarity.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧙‍♂️ My “Old School” Method
&lt;/h2&gt;

&lt;p&gt;Before I start serious work with an agent, I have it learn the project.&lt;/p&gt;

&lt;p&gt;Read the docs 📚 Review the codebase ⚙️ Understand the architecture 🏙️ Learn how to build, test, and run the project locally 👩‍🔧&lt;/p&gt;

&lt;p&gt;I even ask the agent to summarize its understanding back to me.&lt;/p&gt;

&lt;p&gt;This started as a saved prompt, turned into a slash command, and is now a skill.&lt;/p&gt;

&lt;p&gt;This step is a huge productivity boost.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤖 Agents Files (&lt;code&gt;AGENTS.md&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Over the past year, an open standard for providing agents with structured context has emerged.&lt;/p&gt;

&lt;p&gt;Instead of prompting the agent to rediscover your project every time, document that context once — and the agent will reference it going forward.&lt;/p&gt;

&lt;p&gt;Most modern agents support an Agents.md file and reference it during each interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  💽 What Goes in an Agents File?
&lt;/h2&gt;

&lt;p&gt;Think of the Agents file as onboarding documentation, but for an agent.&lt;/p&gt;

&lt;p&gt;Project context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Purpose&lt;/li&gt;
&lt;li&gt;Architecture&lt;/li&gt;
&lt;li&gt;Layout&lt;/li&gt;
&lt;li&gt;CI/CD instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Team context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code style preferences&lt;/li&gt;
&lt;li&gt;Testing philosophy (TDD or YOLO)&lt;/li&gt;
&lt;li&gt;Tech stack constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any tribal knowledge you’d expect a new team member to learn belongs in an Agents file.&lt;/p&gt;

&lt;h2&gt;
  
  
  👨‍💻 Personal Agent Files
&lt;/h2&gt;

&lt;p&gt;Many tools also support a personal Agents file in your home directory.&lt;/p&gt;

&lt;p&gt;That’s where your workflow preferences live. Are you a two-space tabs person? Do you want your agent to prefer table tests?&lt;/p&gt;

&lt;p&gt;If you have preferences you want to apply to every project, but are unique to you, they go in the personal Agents file.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Using an Agents file dramatically improves agent quality.&lt;/p&gt;

&lt;p&gt;Even then, I still use my “learn-this” slash command — sometimes that extra context makes a difference.&lt;/p&gt;

&lt;p&gt;If you wouldn’t drop a new engineer into a project without context, don’t do it to your agents.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>coding</category>
      <category>productivity</category>
    </item>
    <item>
      <title>You can have 100% Code Coverage and still have ticking time bombs in your code. 💣</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 27 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/you-can-have-100-code-coverage-and-still-have-ticking-time-bombs-in-your-code-51hk</link>
      <guid>https://forem.com/madflojo/you-can-have-100-code-coverage-and-still-have-ticking-time-bombs-in-your-code-51hk</guid>
      <description>&lt;p&gt;You can have 100% Code Coverage and still have ticking time bombs in your code. 💣&lt;/p&gt;

&lt;p&gt;I was listening to a team recently, and an engineer was discussing how a coding agent added additional tests to a project that already had 100% code coverage.&lt;/p&gt;

&lt;p&gt;The conversation reminded me that coverage is directional and often mistaken for quality. Just because your coverage shows 100% doesn’t mean your software is fully tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  👨‍🏫 Understanding How Coverage Is Measured
&lt;/h2&gt;

&lt;p&gt;Code Coverage measures the percentage of executable lines that run during code tests. Executed doesn’t mean well-tested.&lt;/p&gt;

&lt;p&gt;Just because every function runs doesn’t mean it’s free of logic errors or safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  😃 Happy Path Testing
&lt;/h2&gt;

&lt;p&gt;A common challenge teams face with testing is focusing too much on the happy path.&lt;/p&gt;

&lt;p&gt;Suppose you have a function that accepts an array. In your tests, you always pass 5 elements — because that’s the expected usage. Coverage shows all branches executed. You’re good, right?&lt;/p&gt;

&lt;p&gt;What happens if you pass 4 elements? Or 0?&lt;/p&gt;

&lt;p&gt;If you never test fewer than 5, how do you know? You may say: “But wait, it’s only ever called with 5 elements.” That may be true, for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ Protecting Against Your Future Self
&lt;/h2&gt;

&lt;p&gt;Code is rarely static; someone will come along and change things. That might be you, it might be someone else.&lt;/p&gt;

&lt;p&gt;Eventually someone changes that function. Will they add tests for new edge cases? Maybe. Assume they won’t.&lt;/p&gt;

&lt;p&gt;When you write tests, don’t just focus on how you know a function is going to be used; also include tests that misuse the function.&lt;/p&gt;

&lt;p&gt;Rather than sending an array with 5 elements, send one with 4, 0, and send a nil value.&lt;/p&gt;

&lt;p&gt;Rather than sending strings that match an expected pattern, send junk that doesn’t.&lt;/p&gt;

&lt;p&gt;Does the function still behave correctly? Should it?&lt;/p&gt;

&lt;p&gt;The more you test outside the happy path, the more resilient your code becomes — and the less likely it is to break later.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Code coverage is a guide, don’t let it give you false confidence. Test the happy path, and the unexpected ones. Validate function outputs against the input you provide.&lt;/p&gt;

&lt;p&gt;100% Coverage is easy. Writing reliable code is not.&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>testing</category>
    </item>
    <item>
      <title>Getting More Out of Agentic Coding Tools</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 20 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/getting-more-out-of-agentic-coding-tools-4l9g</link>
      <guid>https://forem.com/madflojo/getting-more-out-of-agentic-coding-tools-4l9g</guid>
      <description>&lt;p&gt;Are you getting the most out of Agentic Coding Tools?&lt;/p&gt;

&lt;p&gt;Software engineering is changing fast.&lt;/p&gt;

&lt;p&gt;Agentic coding tools became widely available last year, and if you’re not using them today, you’re already behind. But many still struggle to move beyond the “fancy chat” experience.&lt;/p&gt;

&lt;p&gt;Just like any tool in our engineering tool belts, knowing how to use it effectively matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤖 Agents Are More Than A Better Chat
&lt;/h2&gt;

&lt;p&gt;Last year, most were using tab-complete with a useful chat interface where you could ask questions, get suggestions, and maybe copy/paste into your code.&lt;/p&gt;

&lt;p&gt;But agents can do much more than make suggestions — they can understand your codebase and act.&lt;/p&gt;

&lt;p&gt;Instead of asking an agent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Can you suggest additional tests?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tell your agent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Create additional test cases, then run make tests and validate they pass.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An agent can create tests, run them, inspect failures, adjust the implementation, and re-run the suite until it passes.&lt;/p&gt;

&lt;p&gt;This isn’t about suggestions anymore; agents have more autonomy.&lt;/p&gt;

&lt;p&gt;I think of coding agents as assistants working toward a shared goal. They do some work, you do some, and you iterate together.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏆 Moving from Direction to Outcomes
&lt;/h2&gt;

&lt;p&gt;A big mental shift is moving away from simple directions to defining an outcome with guidance &amp;amp; guardrails.&lt;/p&gt;

&lt;p&gt;Agents don’t just perform a single task; they can execute multiple steps (and even parallelize them). You don’t need to spoon-feed each directive one by one.&lt;/p&gt;

&lt;p&gt;Instead, define the outcome you want, along with guidance and guardrails.&lt;/p&gt;

&lt;p&gt;The clearer you are on the outcomes, constraints, and context around what you are trying to do, the better the agent will perform.&lt;/p&gt;

&lt;h2&gt;
  
  
  📋 Examples: Real-world tasks I’ve asked Agents to handle
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Using the existing DB Driver X as a reference, create a set of table tests for driver Y. The tests should be structured similarly to the existing driver, surface any logic issues, concurrency issues, and act as a clear insurance against the defined interface.”&lt;/p&gt;

&lt;p&gt;“Update CI workflows to Go 1.26.0, find and update any references to 1.25.6, then run tests to ensure everything still builds and passes”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I also use agents for mundane work like git commits and opening pull requests. They consistently produce better commit messages and PR descriptions than I would.&lt;/p&gt;

&lt;p&gt;Agents don’t always get it exactly right, but with a bit of feedback and occasional adjustment, you can get a lot done quickly.&lt;/p&gt;

&lt;p&gt;Avoid going down the rabbit hole of endless refinement, sometimes it’s better to reset with a clearer prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  👨‍🏫 Context is Key
&lt;/h2&gt;

&lt;p&gt;If you want the best results from agents, you need to give them context.&lt;/p&gt;

&lt;p&gt;Before I do serious work on a project, I have the agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the Docs 📚&lt;/li&gt;
&lt;li&gt;Review the Architecture 🏙️&lt;/li&gt;
&lt;li&gt;Understand the Project Structure 📐&lt;/li&gt;
&lt;li&gt;Understand how to build, test, and run the application locally 👩‍🔧&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same steps that a human would take. Agents are no different.&lt;/p&gt;

&lt;p&gt;(I’ll dive deeper into Agent files, skills, and effective ways to provide more context in a future post)&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Engineers are doing amazing things with agents, and new capabilities are being added daily. But you don’t need to be at the bleeding edge to get more out of them (I certainly am not).&lt;/p&gt;

&lt;p&gt;Don’t worry about the hype. Understand what these tools can do, making small adjustments in how you use them can drastically change what you get back.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Why is Infrastructure-as-Code so important? Hint: It's correctness</title>
      <dc:creator>Benjamin Cane</dc:creator>
      <pubDate>Fri, 13 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/madflojo/why-is-infrastructure-as-code-so-important-hint-its-correctness-2pao</link>
      <guid>https://forem.com/madflojo/why-is-infrastructure-as-code-so-important-hint-its-correctness-2pao</guid>
      <description>&lt;p&gt;Why is Infrastructure-as-Code so important? Hint: It's correctness.&lt;/p&gt;

&lt;p&gt;I’ve worked on many systems in my career, and one thing that I’ve noticed is that those that leverage infrastructure-as-code tend to be more stable than those that don’t.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 But wait, isn’t everyone using IaC these days?
&lt;/h2&gt;

&lt;p&gt;You may be thinking, "Why am I talking about IaC in 2026? Isn’t this just the de facto standard at this point?"&lt;/p&gt;

&lt;p&gt;My hope is yes, everyone does this, but I’m sure many don’t invest the time into it.&lt;/p&gt;

&lt;p&gt;I’m not here to tell you to use IaC; I’m here to tell you why it’s important, and it’s not necessarily about the speed of deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏎️ Fast is great, but it’s not the biggest benefit
&lt;/h2&gt;

&lt;p&gt;A very clear and correct reason people leverage IaC is the speed of infrastructure provisioning.&lt;/p&gt;

&lt;p&gt;It’s much faster to provision infrastructure with IaC; it takes less time, enabling you to scale faster, and it lets you do cool things like ephemeral environments.&lt;/p&gt;

&lt;p&gt;But the biggest benefit of IaC, in my mind, is correctness.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ IaC reduces human error
&lt;/h2&gt;

&lt;p&gt;Humans make mistakes. When you ask humans to click the same buttons in the same sequence every time, you’ll get mixed results.&lt;/p&gt;

&lt;p&gt;Steps get missed — especially when time passes or people rely on memory instead of process.&lt;/p&gt;

&lt;p&gt;Documentation helps, but there are those of us who think, “I’ve done this a million times, I don’t need instructions.”&lt;/p&gt;

&lt;p&gt;This attitude is the same reason one of my kid’s desks wobbles and the other one doesn’t…&lt;/p&gt;

&lt;p&gt;IaC is a contract. Once defined, every environment is created from the same source of truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Consistency is essential to production stability
&lt;/h2&gt;

&lt;p&gt;The consistency of IaC is what brings production stability.&lt;/p&gt;

&lt;p&gt;When your performance testing environment matches production, your tests become more accurate.&lt;/p&gt;

&lt;p&gt;If one service has a larger memory footprint in testing than it does in production, you might find yourself surprised by out-of-memory errors, especially if heap sizes are configured based on your test environment and not your production environment (because, of course, they would be the same, right?).&lt;/p&gt;

&lt;p&gt;When I come across platforms that use IaC, I see fewer mistakes and fewer incorrect assumptions. And production tends to be more stable, at least with respect to infrastructure and capacity-related issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;So, to answer the question, why is IaC so important? It’s not the speed of provisioning; it’s the correctness of the environments.&lt;/p&gt;

&lt;p&gt;In production systems, correctness beats speed every time.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>devops</category>
      <category>sre</category>
    </item>
  </channel>
</rss>
