<?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: Eyal Bukchin</title>
    <description>The latest articles on DEV Community by Eyal Bukchin (@eyalb).</description>
    <link>https://dev.to/eyalb</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F870070%2Fd01a7af7-a7ae-42a9-9fa1-5f63c974af8f.jpg</url>
      <title>DEV Community: Eyal Bukchin</title>
      <link>https://dev.to/eyalb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eyalb"/>
    <language>en</language>
    <item>
      <title>Testing AI-Generated Code in a Shared Kubernetes Environment</title>
      <dc:creator>Eyal Bukchin</dc:creator>
      <pubDate>Tue, 13 Oct 2026 06:40:48 +0000</pubDate>
      <link>https://dev.to/metalbear/testing-ai-generated-code-in-a-shared-kubernetes-environment-12o</link>
      <guid>https://dev.to/metalbear/testing-ai-generated-code-in-a-shared-kubernetes-environment-12o</guid>
      <description>&lt;p&gt;&lt;em&gt;Written by Arsh Sharma. Originally published on &lt;a href="https://metalbear.com/blog/testing-ai-code-shared-env/" rel="noopener noreferrer"&gt;metalbear.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Research on &lt;a href="https://www.faros.ai/blog/ai-software-engineering" rel="noopener noreferrer"&gt;AI productivity&lt;/a&gt; have been finding out that while AI coding tools measurably increase code output, they don't produce a proportional increase in code merged to production. The gap is the feedback loop, specifically in how long it takes to find out whether generated code actually works in a real environment. In our previous post, we looked at how &lt;a href="https://metalbear.com/blog/testing-bottleneck-ai/#a-better-approach-remocal-testing" rel="noopener noreferrer"&gt;remocal testing&lt;/a&gt; — running your service locally while connected to all of its dependencies in a real Kubernetes cluster — closes that loop for individual developers. But closing it for a &lt;em&gt;team&lt;/em&gt; is a different problem entirely: if multiple developers and/or AI agents are all running local services against the same staging cluster, what prevents them from interfering with each other?&lt;/p&gt;

&lt;h2&gt;
  
  
  The shared environment problem
&lt;/h2&gt;

&lt;p&gt;When an AI agent tests generated code against staging, it interacts with other services in the cluster. It sends requests, consumes messages from queues, and reads and writes to databases. In a shared cluster, those interactions can collide.&lt;/p&gt;

&lt;p&gt;A few specific scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Traffic collisions&lt;/strong&gt;: Two developers both have a locally running instance of the same service to test out code generated by their AI agents. A request comes into the cluster, which they both want redirected to their locally running process to test their code. But which local instance gets it?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queue interference&lt;/strong&gt;: An AI agent generates a queue consumer and starts processing messages from the shared queue. Those messages were meant for other consumers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database corruption&lt;/strong&gt;: AI-generated code runs a migration or executes writes against the shared staging database. Everyone's test data is now affected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The knee-jerk response is to give each developer or AI agent their own isolated environment. But as discussed in the previous post, that &lt;a href="https://metalbear.com/blog/testing-bottleneck-ai/#how-the-industry-is-responding-and-where-it-falls-short" rel="noopener noreferrer"&gt;trades one problem for another&lt;/a&gt;: high infrastructure costs, and environment drift.&lt;/p&gt;

&lt;p&gt;mirrord takes a different approach. Rather than isolating at the environment level, it isolates at the interaction level, filtering which traffic reaches your local process, splitting queues so each developer gets their own copy of messages, and branching databases so changes don't affect shared data. This lets the shared staging cluster stay fully operational for everyone, while each developer's local testing stays isolated to their own interactions.&lt;/p&gt;

&lt;p&gt;Let’s now look at some mirrord features that make testing AI-generated code in a shared Kubernetes cluster safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTTP traffic filtering
&lt;/h2&gt;

&lt;p&gt;By default, when mirrord steals incoming traffic from the cluster to your local process, it steals all of it. Every request that is meant to hit the target service in the cluster gets forwarded to your local instance. Without a way to filter traffic, stealing all incoming traffic to a local process means the service in the cluster stops receiving requests, breaking the environment for everyone else who depends on it.&lt;/p&gt;

&lt;p&gt;mirrord's &lt;a href="https://metalbear.com/mirrord/docs/using-mirrord/incoming-traffic/filter-incoming-traffic" rel="noopener noreferrer"&gt;HTTP traffic filtering&lt;/a&gt; lets you route only requests that match specific criteria (a header, a path, or other filters) to your local process. For example, you can configure mirrord to only forward requests containing a header like &lt;code&gt;baggage: mirrord-session=arsh&lt;/code&gt; to your locally running instance. Every other request continues to go to the live service in the cluster.&lt;/p&gt;

&lt;p&gt;The result is that multiple developers and their AI agents can simultaneously test different changes against the same cluster without worrying about any traffic getting routed to the wrong place.&lt;/p&gt;

&lt;p&gt;For the AI agent, this is particularly useful since it can now send requests repeatedly, observe responses, adjust the generated code, and iterate. All of this while interacting with real dependencies but without touching traffic that belongs to anyone else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Queue splitting
&lt;/h2&gt;

&lt;p&gt;Most modern applications include a message queue like Kafka, SQS, RabbitMQ, or something similar. When an AI agent generates code for a consumer service, testing it against the real cluster creates an immediate conflict because the agent's locally running consumer competes for messages with the existing consumer in the cluster.&lt;/p&gt;

&lt;p&gt;If the generated code is wrong, which it often is on the first iteration, it processes or drops messages other services were expecting to receive. Depending on the system, this can cause cascading failures across your staging environment.&lt;/p&gt;

&lt;p&gt;mirrord's &lt;a href="https://metalbear.com/mirrord/docs/sharing-the-cluster/queue-splitting" rel="noopener noreferrer"&gt;queue splitting&lt;/a&gt; handles this by creating an isolated temporary queue for the local process. The original consumer in the cluster continues processing from the main queue as normal. The locally running service receives its own copy of those messages in a separate queue that only it sees.&lt;/p&gt;

&lt;p&gt;This means the AI agent can run, fail, adjust, and re-run without affecting the shared queue or any other consumers. It gets real messages from the cluster to test against, but those messages are exclusively its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database branching
&lt;/h2&gt;

&lt;p&gt;Database interactions are where AI-generated code most commonly breaks in ways that are hard to catch from reading the code alone. An AI agent might generate a query that doesn't match the actual schema, a migration that conflicts with existing indexes, or write logic that violates data constraints. These only surface when the code runs against a real database.&lt;/p&gt;

&lt;p&gt;But testing against the shared staging database directly is risky. A bad migration, an accidental mass update, or a schema change can break the environment for everyone.&lt;/p&gt;

&lt;p&gt;mirrord's &lt;a href="https://metalbear.com/mirrord/docs/sharing-the-cluster/db-branching" rel="noopener noreferrer"&gt;database branching&lt;/a&gt; creates an isolated branch of the database for the local process. The branch mirrors the schema and data of the real staging database, so tests run against realistic conditions. But writes, migrations, and schema changes only affect that branch, while the shared database is untouched. This lets AI agents test the full range of database interactions without any risk to the rest of the team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional safeguards
&lt;/h2&gt;

&lt;p&gt;HTTP filtering, queue splitting, and database branching cover the most common collision points. But mirrord includes a few more capabilities that help make testing AI-generated code safer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://metalbear.com/mirrord/docs/sharing-the-cluster/policies" rel="noopener noreferrer"&gt;&lt;strong&gt;mirrord Policies&lt;/strong&gt;&lt;/a&gt; let platform teams define guardrails at the cluster level. For example, you can enforce that locally running AI-generated code can never write to shared databases by default, or restrict the namespaces where services can be targeted for stealing. Policies apply across the team so you're not relying on each developer to configure isolation correctly every time.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metalbear.com/mirrord/docs/use-cases/preview-environments" rel="noopener noreferrer"&gt;&lt;strong&gt;Preview environments&lt;/strong&gt;&lt;/a&gt; allow AI agents to deploy code generated for a service as an isolated pod inside the shared staging cluster. This pod runs alongside the stable version of the service and only traffic explicitly routed to it reaches the new pod and everything else continues hitting the live service as normal. This lets you see and share a working version of the changes with stakeholders like product managers, QA, or sales before anything is merged, without needing a separate environment or disrupting anyone else.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metalbear.com/mirrord/docs/use-cases/mirrord-for-ci" rel="noopener noreferrer"&gt;&lt;strong&gt;mirrord for CI&lt;/strong&gt;&lt;/a&gt; extends the remocal testing model to CI pipelines. Instead of provisioning new environments or relying on mocks for CI tests, your pipeline can run tests directly against the same shared staging cluster. This further reduces your cloud bill and the number of environments you have to manage for testing code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  "It'll never work"
&lt;/h2&gt;

&lt;p&gt;Sharing a staging cluster across a full team (and AI agents on top of that) makes people itch with anxiety. The most common objection we hear to the shared environment approach is: there’s no way an entire team can safely work on the same cluster at the same time. What if one AI agent’s generated code does something that breaks the cluster for everyone else? As a response to that personal dev environments for each AI agent seem like the safest bet.&lt;/p&gt;

&lt;p&gt;But in practice, these personal environments don’t hold up because they drift from production, data goes stale, and infrastructure costs compound. And when AI agents are generating and iterating on code faster than any individual developer, the operational overhead of maintaining an environment per agent becomes completely impractical.&lt;/p&gt;

&lt;p&gt;The only model that scales in this case is a shared staging cluster where isolation happens at the interaction level, not the infrastructure level. One cluster, equipped with traffic filtering, queue splitting, and database branching, can support an entire team of developers and AI agents simultaneously, without interference. Each person's testing stays contained to their own interactions. And the environment remains operational for everyone else to keep working.&lt;/p&gt;

&lt;p&gt;This is what mirrord is built for. Large organizations like &lt;a href="https://metalbear.com/mirrord/case-study/monday/" rel="noopener noreferrer"&gt;monday.com&lt;/a&gt;, &lt;a href="https://metalbear.com/mirrord/case-study/zooplus/" rel="noopener noreferrer"&gt;zooplus&lt;/a&gt;, and &lt;a href="https://metalbear.com/mirrord/case-study/surveymonkey/" rel="noopener noreferrer"&gt;SurveyMonkey&lt;/a&gt; already have hundreds of developers using mirrord concurrently, sharing a Kubernetes environment in their organization every day. And as AI agents start running at higher velocity, generating complete features in minutes and iterating on tests in real time, having this infrastructure in place is what will allow you to truly see the benefits from using AI coding tools.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>ai</category>
      <category>testing</category>
      <category>microservices</category>
    </item>
    <item>
      <title>How Our Engineering Team Uses AI, Part II: Meat Proxies</title>
      <dc:creator>Eyal Bukchin</dc:creator>
      <pubDate>Thu, 08 Oct 2026 10:33:43 +0000</pubDate>
      <link>https://dev.to/metalbear/how-our-engineering-team-uses-ai-part-ii-meat-proxies-148g</link>
      <guid>https://dev.to/metalbear/how-our-engineering-team-uses-ai-part-ii-meat-proxies-148g</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://metalbear.com/blog/engineering-ai-use-part-2/" rel="noopener noreferrer"&gt;metalbear.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In January we published &lt;a href="https://metalbear.com/blog/engineering-ai-use/" rel="noopener noreferrer"&gt;How Our Engineering Team Uses AI&lt;/a&gt;. The tl;dr was that AI was useful around the edges of our work (getting oriented in unfamiliar code, exploring approaches, writing scripts) but not much use at the center of it, because mirrord is a low-level Rust tool with an unusual architecture, and general models couldn't really deal with it. We wrapped up the post by calling AI "a powerful tool around the edges of software development."&lt;/p&gt;

&lt;p&gt;Eight months later, we asked the engineering team the same questions again. AI has since moved from the edges to the center: most of the engineers who replied barely write code by hand anymore. Someone still has to read all that code, and so the part of the job that grew the most is review, not only of pull requests, but also the inner loop of reading and correcting (or re-prompting) every chunk of code the agent writes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm not really writing any code, I just review the slop and try to tame the beast.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  We heard you like tools
&lt;/h2&gt;

&lt;p&gt;In Part I, tools converged on ChatGPT, Gemini, Claude Code and Cursor. We still don’t mandate any specific tooling, and now there’s even less standardization among what the team uses. Claude Code and Codex are the most common agents, used through the CLI, the desktop apps, or an editor integration. Beyond that, it's a long tail. Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude inside Emacs, through &lt;a href="https://github.com/xenodium/agent-shell" rel="noopener noreferrer"&gt;agent-shell&lt;/a&gt;, an Emacs package for running coding agents inside the editor.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ampcode.com/" rel="noopener noreferrer"&gt;Amp&lt;/a&gt;, a coding agent and development environment that can work in your local checkout from the terminal or on remote machines it spins up per task.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/stablyai/orca" rel="noopener noreferrer"&gt;Orca&lt;/a&gt;, a desktop app for running several agents in parallel, each in its own git worktree.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/badlogic/pi-mono" rel="noopener noreferrer"&gt;pi&lt;/a&gt;, a minimal open-source agent harness that runs Codex, Claude and Copilot models from one place and is extended with plugins and your own markdown files.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/safishamsi/graphify" rel="noopener noreferrer"&gt;Graphify&lt;/a&gt;, which turns a codebase into a graph agents can query, used to make cheaper Codex models more accurate on our code.&lt;/li&gt;
&lt;li&gt;Gemma running locally through &lt;a href="https://github.com/ggml-org/llama.cpp" rel="noopener noreferrer"&gt;llama.cpp&lt;/a&gt;, for small chores like commits and rebases.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://zed.dev/" rel="noopener noreferrer"&gt;Zed&lt;/a&gt; keeps showing up as well, both for its agent integrations and as a fast, light editor for when a human needs to edit or clean up what the agent wrote.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cost has entered the equation too. By one engineer's estimate, Fable uses about ten times as much of a usage allowance as Opus, and for their work the quality gain was moderate at best, so they stay on Opus. Another engineer tried to save tokens by having a strong model write a detailed implementation guide and handing it to a cheaper model to write the code, since generating output costs more than reading input (alas, the cheaper models wrote code bad enough to make the savings pointless, so this experiment failed).&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it helps
&lt;/h2&gt;

&lt;p&gt;People now use agents for pretty much everything: planning, breaking tickets into subtasks, researching bugs, exploring unfamiliar parts of the codebase, writing code (both on the edges and in the core of the product), writing and running tests, pre-reviewing PRs before asking a human to look at it, diagnosing and fixing CI failures, and investigating production incidents. Some use cases in the general consensus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Finding things by description rather than by name.&lt;/strong&gt; When you're working with e.g. an unfamiliar Kubernetes data model, you often don't know what the thing you're looking for is called, so you can't grep for it, but you can describe it. Agents are very good at this kind of search.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code outside the product.&lt;/strong&gt; Build tooling, bash scripts, and throwaway tests for checking locally how our infrastructure behaves in an edge case (like how a queue handles some unusual sequence of events). The stakes are low, since a mistake breaks a build step or a local experiment rather than something a customer runs. Our &lt;code&gt;xtask&lt;/code&gt; build scripts were described as something "no human hand has ever touched."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status updates.&lt;/strong&gt; The age-old chore of keeping Linear issues and status posts current can finally be outsourced.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Questions about past decisions.&lt;/strong&gt; Why a component was designed the way it was, or what was decided about a feature, is often faster to ask an agent than to track down the person who made the call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collecting and analyzing messy data.&lt;/strong&gt; That's how we found our flakiest tests and measured how our CI changes affected run durations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Work a script should be doing.&lt;/strong&gt; For repetitive tasks nobody has automated yet, having an agent do the work each time is slower and more expensive than a script would be, but we’re lazy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where it still struggles
&lt;/h2&gt;

&lt;p&gt;Rust quality remains a recurring complaint. Agent-written Rust compiles, but it tends to be much longer than it needs to be, with unnecessary &lt;code&gt;.to_owned()&lt;/code&gt;, &lt;code&gt;.clone()&lt;/code&gt; and &lt;code&gt;.collect()&lt;/code&gt; calls that someone then has to go through and remove. Agents are also eager to write tests, and love splitting code into tiny functions so they can add tiny tests for them. Even the engineers who have moved furthest toward AI still evaluate every line and the overall structure of a change themselves, and they often find it wanting.&lt;/p&gt;

&lt;p&gt;Agents also tend to reinvent things. Ask one how to solve a problem and it will often come up with its own solution instead of finding the library or well-known approach that already solves it, so its research is a starting point rather than an answer. So most engineers prefer to do the initial research for a new area by hand. The point is for the engineer to understand the problem space deeply enough to make good calls on everything built on top of it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Writing the PR description/commits makes me look at the problem from a higher level, which ensures I at the very least understand the solution and can judge it appropriately.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The strongest opinions were about writing style. Several engineers write every commit message, PR description and code comment themselves, because agents produce too much of it and too little of it makes sense. Those who let agents draft docs or RFCs usually end up rewriting most of it, because, as one put it, "AI generated text reads like word pulp." But the best argument for doing it by hand is that writing the PR description forces you to look at the problem from a higher level, which can help ensure you understood the solution well enough.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI generated text reads like word pulp.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  We mostly just review now
&lt;/h2&gt;

&lt;p&gt;Asked how their usage had changed since January, one engineer described much more parallelism and much more fatigue:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My week used to be 20-40% reviews, 60-80% code gen, now it's 95% reviews, it's so tiring.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Others described something close to burnout. A task now takes more rounds of reviewing and correcting before it's actually finished, so finishing feels further away than it used to, and with several agents running, you're in that state on several tasks at once. Some refuse the parallelism altogether, running a single agent thread with a narrow purpose and thinking carefully about what comes back.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;i only use 1 thread at a time with a very specific purpose and think about things carefully. all those agent orchestrators and stuff are too much for me, it feels like the fastest way to get burnout&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The most difficult part is keeping control over quality and maintaining an understanding of how the system works. Even the engineers who no longer write code by hand still go through several review passes after the code works, until they understand and have tested every line. Everyone works hard to not become meat proxies.&lt;/p&gt;

&lt;p&gt;We’re trying to find solutions, though, and right now we’re hoping we can successfully automate the first pass. Greptile reviews our pull requests automatically (we’re currently evaluating it against Qodo, using AI to run the evaluation), and many of us have an agent review our own PR before a person sees it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building for the agent that will maintain it
&lt;/h2&gt;

&lt;p&gt;There were also changes in how people design things. Some of us now build with the assumption that an agent will maintain the code, which in practice means thorough logging, so that an agent debugging it later has something to read (a courtesy I’m sure many humans would have also appreciated). Some write personal skills that encode their repeated rules and fixes.&lt;/p&gt;

&lt;p&gt;That has a company-level version. The January post showed the CLAUDE.md in our mirrord repo, which back then included a long architecture walkthrough. It has since become an &lt;a href="https://github.com/metalbear-co/mirrord/blob/main/AGENTS.md" rel="noopener noreferrer"&gt;AGENTS.md&lt;/a&gt;, with CLAUDE.md as a link to it, and it got shorter: the walkthrough was deemed unnecessary and cut, leaving a one-line description of each core component plus the commands for building, testing and linting. It now sits alongside a company-wide one. Everyone at MetalBear imports one shared context repository from their personal &lt;code&gt;~/.claude/CLAUDE.md&lt;/code&gt;, which describes our teams, the tools we use and the known quirks of each, so every agent starts from the same background. The repository is private, but the pattern is simple enough to copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  One engineer's experiment with agents on a schedule
&lt;/h2&gt;

&lt;p&gt;One of our engineers has been experimenting with agents that run on a schedule rather than on request. One agent triages CI every night. Another picks one small, open bug from Linear every morning and opens a PR to fix it. Tiny but non-critical is a category of work that people never get around to and agents don't mind.&lt;/p&gt;

&lt;p&gt;The same engineer also built a support bot that our solutions engineers use to draft answers, which a human then checks and sends. After it confidently described an unverified configuration as "confirmed working in a past similar case," it got two standing rules: search past resolutions before reasoning from scratch, and end every answer with what it is based on.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what changed?
&lt;/h2&gt;

&lt;p&gt;In January, AI was a tool around the edges of our work. Now, thanks to models improving, our processes maturing, and simply the time it takes workflow changes to propagate, AI writes most of the code for many of the engineers who answered. The work that grew is making sure a person understood that code before it ships. It is certainly more tiring, and hopefully our next post on this will be about how we solved that.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>engineering</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Build vs. Buy Your Kubernetes Development Environment</title>
      <dc:creator>Eyal Bukchin</dc:creator>
      <pubDate>Wed, 07 Oct 2026 10:43:26 +0000</pubDate>
      <link>https://dev.to/metalbear/build-vs-buy-your-kubernetes-development-environment-13hm</link>
      <guid>https://dev.to/metalbear/build-vs-buy-your-kubernetes-development-environment-13hm</guid>
      <description>&lt;p&gt;&lt;em&gt;Written by Arsh Sharma. Originally published on &lt;a href="https://metalbear.com/blog/build-vs-buy/" rel="noopener noreferrer"&gt;metalbear.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every conversation about buying a dev tool now includes a brief silence in which someone mentally scopes building it instead. The instinct isn't new, engineers have always been one whiteboard session away from replacing any product with a quarterly project. But Claude Code has compressed that quarterly project into a weekend.&lt;/p&gt;

&lt;p&gt;And the truth is, with AI, a capable platform engineer probably &lt;em&gt;could&lt;/em&gt; build a working prototype in a sprint: something that connects a developer's code (running on a laptop, in an agent's sandbox, or in CI) and the remote staging cluster, letting them test against real services without deploying every single time. The mistake is thinking that sprint gets you the finished product. Noting the obvious bias we have as a vendor, here's what we've learned from building and maintaining a Kubernetes development platform: what the other 90% of the work looks like, what it actually costs, and how to decide whether buying or building is the right call.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is mirrord?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://metalbear.com/mirrord/" rel="noopener noreferrer"&gt;mirrord&lt;/a&gt; is a Kubernetes development platform that lets developers and AI coding agents test code in a production-like environment before deploying it. Traditionally, giving developers a realistic environment to test in means one of two things: spinning up an ephemeral dev/test environment for each of them or having everyone wait their turn to deploy to staging. &lt;a href="https://metalbear.com/blog/enabling-developers-to-ship-cloud-native-applications-faster/" rel="noopener noreferrer"&gt;Both are slow&lt;/a&gt; because every iteration means building images and deploying. Ephemeral environments also get expensive fast since you're duplicating infrastructure for every developer.&lt;/p&gt;

&lt;p&gt;mirrord takes a different approach: all developers in the organization share a single staging cluster, and each runs their service wherever they're working, be it locally on their machine, in a CI runner, or in an agent's sandbox. mirrord then proxies incoming and outgoing traffic, environment variables, and files between the local process and its counterpart deployed in the cluster. The running service behaves as if it were deployed since it receives real requests and talks to the cluster's real services, databases, and queues. Because of this, the code behaves as it would in the context of the entire application without actually deploying it. And because everyone shares a cluster that already exists, there's nothing ephemeral to spin up and no duplicated infrastructure to pay for.&lt;/p&gt;

&lt;p&gt;At first glance, building what mirrord does might look like a sprint's worth of work. A platform engineer can stitch together a proof of concept with &lt;code&gt;kubectl port-forward&lt;/code&gt; and some scripting in a week or two: run the new version of a service beside the deployed one, tag requests with a header, and route only the tagged requests to it. The demo works, the new code is testable against real dependencies without deploying it, and paying for a tool starts to feel absurd when your own team just built the core of one in a sprint.&lt;/p&gt;

&lt;p&gt;LaunchDarkly &lt;a href="https://launchdarkly.com/blog/feature-management-platform-build-or-buy/" rel="noopener noreferrer"&gt;wrote about this exact pattern&lt;/a&gt; with feature flags: a feature flag is just an if statement, so building a feature management platform looks trivial until you realize that every capability that makes it actually useful turns out to be its own project, requiring you to invest more and more engineering time into it. Our version of "it's just an if statement" is "it's just a proxy." And in both cases, what people miss is that the demo is not the finished product.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the other 90% actually costs
&lt;/h2&gt;

&lt;p&gt;Here's what that hidden 90% of work after the initial prototype consists of.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing the cluster is the hard part
&lt;/h3&gt;

&lt;p&gt;We've &lt;a href="https://metalbear.com/blog/celonis-mirrord/" rel="noopener noreferrer"&gt;written extensively&lt;/a&gt; about the benefits of shared environments over dedicated ephemeral ones in the past, so we'll assume here that the tool you're building targets a shared cluster, usually staging, like mirrord does.&lt;/p&gt;

&lt;p&gt;The tool has two jobs. The first is letting a developer quickly test their locally running code against that production-like cluster, and this is probably what your proof of concept will cover. The second job is letting every developer do this at the same time, against the same cluster, without stepping on each other. This is where the scope explodes, especially because developers aren't the only users anymore. With every developer now launching multiple agents and pointing them to the same cluster to verify the code they just generated, a hundred engineers can easily mean several hundred sessions sharing the cluster.&lt;/p&gt;

&lt;p&gt;The conflict everyone scopes for is traffic: two developers can't both receive all the requests hitting a service, so you obviously need &lt;a href="https://metalbear.com/mirrord/docs/using-mirrord/incoming-traffic/filter-incoming-traffic" rel="noopener noreferrer"&gt;HTTP filtering&lt;/a&gt; that routes each developer's requests to the right session, and you could say that part is fairly easy to build as well. What usually goes unscoped is everything else that collides. Two local processes compete for the same queue messages, so you need queue-splitting logic that routes each message to the right session. They write to the same database, so you need a way to give each developer an isolated copy. This is why mirrord has features like &lt;a href="https://metalbear.com/mirrord/docs/sharing-the-cluster/queue-splitting" rel="noopener noreferrer"&gt;queue splitting&lt;/a&gt;, &lt;a href="https://metalbear.com/blog/db-branching/" rel="noopener noreferrer"&gt;database branching&lt;/a&gt;, and &lt;a href="https://metalbear.com/mirrord/docs/sharing-the-cluster/policies" rel="noopener noreferrer"&gt;mirrord Policies&lt;/a&gt; that make sharing a cluster &lt;a href="https://metalbear.com/mirrord/case-study/zooplus/" rel="noopener noreferrer"&gt;among thousands of developers&lt;/a&gt; possible. Each is a significant engineering effort on its own, and none of them will be in your v1.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your R&amp;amp;D org pays the real bill
&lt;/h3&gt;

&lt;p&gt;Say your five-person platform team spends six months building this. The visible cost is five salaries for six months plus some ongoing maintenance cost, and depending on your budget, that might look fine. But there's a bigger number. Every day the tool isn't finished is another day your hundred-person R&amp;amp;D org keeps working with the slow dev loop you set out to fix (&lt;a href="https://metalbear.com/blog/kubernetes-dev-loop-cost/" rel="noopener noreferrer"&gt;here's how to put a number on what that costs&lt;/a&gt;). The meter isn't just running on the team building the tool, it's running on everyone waiting for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finished isn't adopted
&lt;/h3&gt;

&lt;p&gt;Internal devtools only pay off if engineers actually use them, and the adoption bar is high: the tool should be easy to set up, easy to use, and stable enough that developers trust it with their daily workflow. That trust is hard to earn in the first place because developers don't rush to try untested internal tools. And it's even harder to earn back: a developer who tried v1, hit a rough edge, and went back to their old workflow isn't returning for v2 just because you tell them that things got better. If the experience is clunky, engineers are less likely to file feature requests and more likely to just quietly work around the tool and avoid using it.&lt;/p&gt;

&lt;p&gt;This creates an awkward loop for an in-house built tool. You don't reach that quality bar with just a good design document and a prompt. You reach it by iterating against real developer feedback repeatedly, which means that even after you're "done" building, you're not really done. You still need to see what features your team needs that are missing, what parts aren't stable, and constantly build towards them. But that iteration needs developers actually using the tool, and the rough early versions are exactly what teaches them to stay away. It's also the stage AI doesn't really speed up, because the bottleneck is developers hitting friction and telling you about it, not writing the code faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Long term support
&lt;/h3&gt;

&lt;p&gt;The work doesn't end once the tool is built, because the ground underneath it never stops moving: Kubernetes ships three releases a year, service mesh upgrades can change how traffic flows, and new protocols show up in your stack. Each of these lands on your team as a support request, and each one forces the same choice, either sink more engineering time into the in-house tool or leave the gap unsupported.&lt;/p&gt;

&lt;p&gt;What makes this a losing game internally is who you're doing it for. Every one of those investments serves the same few hundred engineers at your company, so each round of maintenance gets harder to justify against everything else on the platform team's backlog. That exact same work is easy for us to justify, because a fix or a newly supported protocol ships to tens of thousands of engineers across all the companies using mirrord.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why vibe coding this isn't as easy as it seems
&lt;/h2&gt;

&lt;p&gt;AI has changed the math around the build vs. buy argument: an agent can scaffold a proof of concept in an afternoon instead of a sprint, so building is cheaper than ever. The first half of that is true, and it actually makes the trap worse, because the demo now arrives even faster while the 90% below the waterline still remains a hard problem to solve.&lt;/p&gt;

&lt;p&gt;We have some direct experience here. mirrord is a low-level systems tool built in Rust, our engineering team uses AI every day while building it, and we've written candidly about &lt;a href="https://metalbear.com/blog/engineering-ai-use/" rel="noopener noreferrer"&gt;how that actually goes&lt;/a&gt;. AI is genuinely useful for things like getting oriented in unfamiliar code, exploring approaches, generating scripts to debug things. But all these require the code to already exist. Vibe coding a tool like this from scratch is a totally different experience. With no existing codebase to ground the model in, no domain experts to review the output, and months of sustained work instead of a single scoped session, you're trusting the model exactly where it's the weakest: short on context, unsupervised, and running for months.&lt;/p&gt;

&lt;p&gt;Even with engineers who know the architecture reviewing every line, and CLAUDE.md files we maintain specifically to feed models that context, we've had very few cases of AI shipping a real feature in mirrord without heavy manual intervention.&lt;/p&gt;

&lt;h2&gt;
  
  
  The TCO comparison
&lt;/h2&gt;

&lt;p&gt;Here's what the two options actually cost. The build numbers come from what we've seen teams scope once they get past the proof of concept.&lt;/p&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;Build internally&lt;/th&gt;
&lt;th&gt;Buy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Time to a usable v1&lt;/td&gt;
&lt;td&gt;6+ months&lt;/td&gt;
&lt;td&gt;~1 week&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project maturity at launch&lt;/td&gt;
&lt;td&gt;Your engineers discover every failure mode first&lt;/td&gt;
&lt;td&gt;Years of hardening across various customers (4+ years and 20,000+ users, in mirrord's case)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shared-environment support&lt;/td&gt;
&lt;td&gt;Another 3-6 months of engineering work.&lt;/td&gt;
&lt;td&gt;Already supported through features like DB branching, queue splitting, and traffic filtering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ongoing maintenance&lt;/td&gt;
&lt;td&gt;Your roadmap, indefinitely&lt;/td&gt;
&lt;td&gt;The vendor's roadmap, no maintenance on your side&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;When it breaks&lt;/td&gt;
&lt;td&gt;Your team gets paged, your developers wait&lt;/td&gt;
&lt;td&gt;A dedicated team that has probably seen the failure mode before&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  A decision checklist
&lt;/h2&gt;

&lt;p&gt;Questions worth answering with your team before committing either way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Can you staff it like a product?&lt;/strong&gt; Not just 3–5 systems engineers for the six month, but permanent ownership afterward including being on-call and supporting upgrades.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does your v1 scope include more than the happy path?&lt;/strong&gt; If the plan doesn't mention queue splitting, database isolation, or mesh compatibility, the plan covers only the 10% above the waterline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What does an outage cost you?&lt;/strong&gt; If the answer is "every developer is blocked," your internal tool needs production-grade reliability from day one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Will engineers actually adopt it?&lt;/strong&gt; If the experience isn't seamless, engineers work around it, and you end up maintaining a tool nobody uses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does the plan account for AI agents?&lt;/strong&gt; Coding agents that test their own changes multiply concurrent sessions and need the same isolation guarantees as developers. Scoping for humans only means rebuilding for agents later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do you have a genuinely unusual constraint?&lt;/strong&gt; Regulatory requirements that no vendor can meet are real reasons to build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you answered yes to most of these, building may honestly be the right call for you. For everyone else, the math points the other way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where mirrord fits
&lt;/h2&gt;

&lt;p&gt;mirrord lets developers and AI agents run their code on a laptop, in a CI runner, or in an agent's sandbox while connected to a real cluster. Incoming traffic, outgoing calls, environment variables, and files all behave as if the process were running inside the cluster, with no image builds or deployments in the loop. And because a mirrord session is just a CLI command, an agent can run the code it just wrote against the real cluster and verify it actually works, instead of &lt;a href="https://metalbear.com/blog/after-ai-writes-code/" rel="noopener noreferrer"&gt;guessing or making assumptions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The shared-environment features that make up the bulk of the iceberg (queue splitting, database branching, traffic filtering) are &lt;a href="https://metalbear.com/mirrord/docs" rel="noopener noreferrer"&gt;already built&lt;/a&gt;, which is how teams like &lt;a href="https://metalbear.com/mirrord/case-study/monday/" rel="noopener noreferrer"&gt;monday.com&lt;/a&gt; and &lt;a href="https://www.linkedin.com/posts/the-metalbear-team-had-the-pleasure-of-delivering-ugcPost-7476264187795533824-Ge1f/?utm_source=share&amp;amp;utm_medium=member_desktop&amp;amp;rcm=ACoAACZv8bIBvRMtv8vhCxDwho1OafMsqDmeHtM" rel="noopener noreferrer"&gt;National Australia Bank (NAB)&lt;/a&gt; run it for hundreds of engineers against a single shared environment.&lt;/p&gt;

&lt;p&gt;But that's not only what mirrord does. Since this is our main product we've built tons of features on top of it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://metalbear.com/blog/preview-environments/" rel="noopener noreferrer"&gt;&lt;strong&gt;Preview Environments&lt;/strong&gt;&lt;/a&gt;: Every pull request spins up a thin preview environment where only the work-in-progress service is duplicated in the cluster as an isolated pod. Reviewers like product managers, QA, or designers get a URL to see real behavior against real services before anything is merged.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metalbear.com/blog/mirrord-ci/" rel="noopener noreferrer"&gt;&lt;strong&gt;mirrord for CI&lt;/strong&gt;&lt;/a&gt;: The same model applied to pipelines. Your PR's code runs in the CI runner but is tested against the real cluster, so there's no ephemeral environment to spin up in CI and no images to build and deploy, which saves teams 20–25 minutes per CI run, with concurrent runs kept isolated from each other and from developers using the same cluster.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://metalbear.com/mirrord/docs/managing-mirrord/admin-dashboard" rel="noopener noreferrer"&gt;&lt;strong&gt;Admin Dashboard&lt;/strong&gt;&lt;/a&gt;: A web interface for the platform team running mirrord, with real-time visibility into mirrord sessions, users, targets, CI pipelines, and adoption trends across the organization. Allows platform teams who buy the tools to show adoption, usage, and ROI to stakeholders.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whichever way your team decides, price the whole iceberg and not just the part above the water.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked build vs. buy questions
&lt;/h2&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Should I build or buy a Kubernetes development environment?
&lt;/h3&gt;

&lt;p&gt;It depends on whether you can staff it like a product, not just a project. A capable platform team can prototype the core behavior you need in a sprint, but a production-grade version that supports your whole org with features like sharing a cluster across hundreds of developers without collisions, and getting maintained as Kubernetes and your stack evolve, usually takes 6+ months and permanent ongoing ownership. If you have that staffing and a genuinely unusual constraint a vendor can't meet, building can be the right call. For most teams, the math favors buying.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does AI make it easier to build internal tools in-house?
&lt;/h3&gt;

&lt;p&gt;AI makes the demo faster to reach, not the finished product. AI coding agents are genuinely useful once a codebase already exists: getting oriented, exploring approaches, writing debug scripts. But building a Kubernetes development platform from scratch means months of sustained work with no existing codebase to ground the model and no domain experts reviewing every line, which is exactly the setup AI handles worst. It also doesn't speed up the part of the work that matters most for adoption: iterating on real developer feedback.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does it cost to maintain an in-house Kubernetes dev tool?
&lt;/h3&gt;

&lt;p&gt;Beyond the initial build, ongoing maintenance means keeping up with three Kubernetes releases a year, service mesh upgrades that can change how traffic flows, and new protocols showing up in your stack, each landing on your platform team as a support request. That work only serves the few hundred engineers at your company, so it competes against everything else on the team's backlog indefinitely. A vendor absorbs that same maintenance across tens of thousands of engineers, which is why it's easier for them to justify.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does mirrord handle multiple developers sharing one staging cluster?
&lt;/h3&gt;

&lt;p&gt;mirrord uses features purpose-built for this: &lt;a href="https://metalbear.com/mirrord/docs/using-mirrord/incoming-traffic/filter-incoming-traffic" rel="noopener noreferrer"&gt;HTTP traffic filtering&lt;/a&gt; routes each developer's requests to their session, &lt;a href="https://metalbear.com/mirrord/docs/sharing-the-cluster/queue-splitting" rel="noopener noreferrer"&gt;queue splitting&lt;/a&gt; routes each queue message to the right session, and &lt;a href="https://metalbear.com/blog/db-branching/" rel="noopener noreferrer"&gt;database branching&lt;/a&gt; gives each developer an isolated copy of the data they touch. These are already in use for &lt;a href="https://metalbear.com/mirrord/case-study/zooplus/" rel="noopener noreferrer"&gt;thousands of developers&lt;/a&gt; across companies like monday.com and NAB, rather than something a team has to build and harden on its own.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>platformengineering</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Auto-verifying your AI-SRE's fixes (Part II): HolmesGPT end-to-end on a real cluster</title>
      <dc:creator>Eyal Bukchin</dc:creator>
      <pubDate>Wed, 24 Jun 2026 12:18:12 +0000</pubDate>
      <link>https://dev.to/metalbear/auto-verifying-your-ai-sres-fixes-part-ii-holmesgpt-end-to-end-on-a-real-cluster-594p</link>
      <guid>https://dev.to/metalbear/auto-verifying-your-ai-sres-fixes-part-ii-holmesgpt-end-to-end-on-a-real-cluster-594p</guid>
      <description>&lt;p&gt;&lt;em&gt;Part II of two. See &lt;a href="https://metalbear.com/blog/ai-sre/" rel="noopener noreferrer"&gt;Part I&lt;/a&gt; for the recipe.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://metalbear.com/blog/ai-sre/" rel="noopener noreferrer"&gt;Part I&lt;/a&gt; we've discussed how you can plug mirrord into your AI-SRE so it can autonomously test its fix in the real cluster. In this post, we'll show this running end-to-end on a real GKE cluster against &lt;a href="https://github.com/robusta-dev/holmesgpt" rel="noopener noreferrer"&gt;HolmesGPT&lt;/a&gt;, the only OSS AI-SRE we found that is self-hostable. We planted two bugs to test both possible verdicts: PASS when the patched run clears the alert's SLO without any regressions, REJECT when it doesn't (the patched run still violates the alert's SLO, or cleared the SLO but added a regression).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt; &lt;strong&gt;HolmesGPT&lt;/strong&gt; investigates an alert and returns a markdown report. A &lt;strong&gt;small Claude wrapper&lt;/strong&gt; turns the report into a code patch. The &lt;strong&gt;verifier&lt;/strong&gt; runs that patch under &lt;code&gt;mirrord exec&lt;/code&gt;, compares against an unpatched baseline, and returns a verdict tied to the alert's actual SLO.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fss4lp3lpxeumlmozf1qj.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fss4lp3lpxeumlmozf1qj.png" alt="AI-SRE verification architecture" width="800" height="1185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What's HolmesGPT?&lt;/strong&gt; A prebuilt LLM-backed agent tailored for on-call work: it can run &lt;code&gt;kubectl&lt;/code&gt; commands, fetch logs from the cluster, and read the runbooks you've already written (in Notion, Confluence, or markdown files) to ground its investigation. Without it, you'd be building this scaffolding around Claude yourself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The demo cluster
&lt;/h2&gt;

&lt;p&gt;A Python service called &lt;code&gt;checkout&lt;/code&gt; handles HTTP requests; on each request it calls a &lt;code&gt;pricing&lt;/code&gt; service for the item price. A &lt;code&gt;loadgen&lt;/code&gt; pod hits &lt;code&gt;checkout&lt;/code&gt; continuously to keep the system warm. Prometheus scrapes &lt;code&gt;checkout&lt;/code&gt;'s metrics; Alertmanager fires when SLOs are violated. Everything sits in one namespace.&lt;/p&gt;

&lt;p&gt;HolmesGPT runs as a pod in the cluster, subscribed to Alertmanager. When an alert fires, HolmesGPT investigates and hands its markdown report off to a separate verifier pod. The verifier runs the bridge (the Claude call that turns the report into a code patch), then uses &lt;code&gt;mirrord exec&lt;/code&gt; to run the patched code inside the verifier pod with &lt;code&gt;deploy/checkout&lt;/code&gt;'s network identity, env, and mounts. When the patched copy calls &lt;code&gt;pricing&lt;/code&gt;, it hits the real &lt;code&gt;pricing&lt;/code&gt; pod.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1k20qfp7va1thxax4wzh.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1k20qfp7va1thxax4wzh.png" alt="Demo cluster layout" width="800" height="905"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Scenario 1: error-rate alert (PASS)
&lt;/h2&gt;

&lt;p&gt;A recent change introduced a request format &lt;code&gt;checkout()&lt;/code&gt; doesn't handle: every request for an &lt;code&gt;item_id&lt;/code&gt; ending in &lt;code&gt;-3&lt;/code&gt; raises &lt;code&gt;ValueError&lt;/code&gt; and returns 500. Loadgen sends a mix; ~10% of requests fail. A Prometheus rule fires &lt;code&gt;CheckoutErrorRateHigh&lt;/code&gt; once the error rate climbs over 5%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ask HolmesGPT to investigate.&lt;/strong&gt; This is the call HolmesGPT runs in-cluster when Alertmanager fires:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;holmes investigate alertmanager &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--alertmanager-url&lt;/span&gt; http://localhost:9093 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--alertmanager-alertname&lt;/span&gt; CheckoutErrorRateHigh &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--model&lt;/span&gt; &lt;span class="s1"&gt;'anthropic/claude-sonnet-4-20250514'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HolmesGPT investigated for ~30 seconds (pulled pod descriptions, fetched logs, walked the service config) and concluded:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Root Cause:&lt;/strong&gt; Application logic error causing 500 responses for specific item (item-3)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error Details:&lt;/strong&gt; Error rate: 20.09% (above 5% SLO). Specific error: &lt;code&gt;ValueError: unsupported catalog shape for item_id=item-3&lt;/code&gt;. Pattern: repeated failures for item-3 checkout requests returning HTTP 500.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remediation:&lt;/strong&gt; Fix application code to handle item-3 catalog shape or add proper validation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clean diagnosis: HolmesGPT pulled the exception out of the logs and attributed it correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bridge to a code patch.&lt;/strong&gt; HolmesGPT outputs a markdown report, not a &lt;code&gt;git diff&lt;/code&gt;. The bridging step is a small Claude call running in the verifier pod that takes the report plus the service's source and returns a code patch. We asked it to faithfully implement HolmesGPT's recommendation: handle the item-3 case (Claude chose to return zero) rather than raising. Claude produced the minimal edit to &lt;code&gt;checkout.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verify.&lt;/strong&gt; Two runs (baseline and patched), 100 requests each. The verifier compares the alert's SLO condition against the patched run, plus a regression watchlist on the other signals. The "baseline" here is the verifier's own load test on the unpatched code, same load and same downstream as the patched run, not the live error rate HolmesGPT observed. That's why the number below differs from the 20.09% in HolmesGPT's report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SLO under verification:&lt;/strong&gt; &lt;code&gt;error_rate &amp;gt; 5%&lt;/code&gt; (alert fires while this holds)&lt;/p&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;Baseline&lt;/th&gt;
&lt;th&gt;Patched&lt;/th&gt;
&lt;th&gt;SLO threshold&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Error rate&lt;/td&gt;
&lt;td&gt;10.00%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.00%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5.00%&lt;/td&gt;
&lt;td&gt;✅ satisfies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Regression watchlist&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Baseline&lt;/th&gt;
&lt;th&gt;Patched&lt;/th&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;p50 latency (ms)&lt;/td&gt;
&lt;td&gt;469.2&lt;/td&gt;
&lt;td&gt;470.5&lt;/td&gt;
&lt;td&gt;+0.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;p99 latency (ms)&lt;/td&gt;
&lt;td&gt;505.7&lt;/td&gt;
&lt;td&gt;531.8&lt;/td&gt;
&lt;td&gt;+5.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Verdict: PASS.&lt;/strong&gt; Alert condition &lt;code&gt;error_rate &amp;gt; 5%&lt;/code&gt; no longer satisfied (10% → 0%). Regression watchlist clean.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scenario 2: latency alert (REJECT)
&lt;/h2&gt;

&lt;p&gt;The error-rate bug was easy: a literal exception in the logs with an obvious fix. What does the loop look like for a less log-visible bug? We swapped in the second planted defect: &lt;code&gt;fetch_price()&lt;/code&gt; has no client-side timeout, and &lt;code&gt;pricing&lt;/code&gt; has a long tail: 1 in 10 calls takes ~1.5s. p99 drifts to ~2 seconds, well above the 300ms SLO. &lt;code&gt;CheckoutP99High&lt;/code&gt; fires.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ask HolmesGPT:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;holmes investigate alertmanager &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--alertmanager-url&lt;/span&gt; http://localhost:9093 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--alertmanager-alertname&lt;/span&gt; CheckoutP99High &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--model&lt;/span&gt; &lt;span class="s1"&gt;'anthropic/claude-sonnet-4-20250514'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Root Cause Analysis:&lt;/strong&gt; Latency caused by synchronous dependency calls (each checkout request triggers pricing API calls), no apparent caching, potential bottleneck in pricing service.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Implement caching for pricing data to reduce API calls&lt;/li&gt;
&lt;li&gt;Add async processing for non-critical pricing lookups&lt;/li&gt;
&lt;li&gt;Monitor pricing service performance and scaling&lt;/li&gt;
&lt;li&gt;Consider request batching to pricing service&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;Caching is a reasonable optimization. It's also generally a good idea. The question is whether it resolves &lt;em&gt;this specific alert&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bridge:&lt;/strong&gt; Of the four recommendations, only caching is a single code change; the others are runtime tuning or architectural refactors. Claude implemented it as an in-memory TTL cache around &lt;code&gt;fetch_price()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verify.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SLO under verification:&lt;/strong&gt; &lt;code&gt;p99 latency (ms) &amp;gt; 300&lt;/code&gt;&lt;/p&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;Baseline&lt;/th&gt;
&lt;th&gt;Patched&lt;/th&gt;
&lt;th&gt;SLO threshold&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;p99 latency (ms)&lt;/td&gt;
&lt;td&gt;2162.5&lt;/td&gt;
&lt;td&gt;2010.3&lt;/td&gt;
&lt;td&gt;300.0&lt;/td&gt;
&lt;td&gt;❌ violates&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Regression watchlist:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Baseline&lt;/th&gt;
&lt;th&gt;Patched&lt;/th&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;p50 latency (ms)&lt;/td&gt;
&lt;td&gt;529.8&lt;/td&gt;
&lt;td&gt;0.9&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−99.8%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error rate&lt;/td&gt;
&lt;td&gt;0.00%&lt;/td&gt;
&lt;td&gt;0.00%&lt;/td&gt;
&lt;td&gt;no change&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Verdict: REJECT.&lt;/strong&gt; Alert would still be firing post-merge. SLO &lt;code&gt;p99_ms &amp;gt; 300.0&lt;/code&gt; (baseline 2162, patched 2010).&lt;/p&gt;

&lt;p&gt;p50 dropped 99.8% (cache hits return instantly), but the 99th-percentile request is still a cache miss hitting the 1.5s tail. The alert-aware classifier says the thing the on-call needs to hear: &lt;em&gt;the alert that fired would still fire on this code; SLO threshold 300ms; patched value 2010ms.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The fix HolmesGPT didn't propose: a short client-side timeout on &lt;code&gt;fetch_price()&lt;/code&gt; to fail-fast under the SLO instead of waiting out the 1.5s tail. We re-ran the bridge with a hand-crafted patch doing that; verifier returned PASS at patched p99 ~330ms. The point isn't that HolmesGPT missed the right fix, it's that the verifier surfaced the gap before the wrong patch shipped.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the two scenarios show
&lt;/h2&gt;

&lt;p&gt;The loop closes against a real OSS AI-SRE you can install yourself. HolmesGPT investigates, the bridge turns its report into a patch, mirrord runs it against the live cluster, the classifier returns a verdict tied to the actual alert. No integration code from us.&lt;/p&gt;

&lt;p&gt;PASS and REJECT both have to be useful or the verifier becomes decorative. Scenario 1 signs off on a real fix. Scenario 2 stops one that &lt;em&gt;looks&lt;/em&gt; good (p50 −99.8%) but doesn't clear the alert. Without both, on-call learns to ignore the verifier and starts merging on faith.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run it yourself
&lt;/h2&gt;

&lt;p&gt;The sample &lt;code&gt;checkout&lt;/code&gt;/&lt;code&gt;pricing&lt;/code&gt; services, Prometheus rules, verifier code, and bridge script are small (~500 lines of Python plus the ~80-line bridge). The code lives at &lt;a href="https://github.com/metalbear-co/holmes-mirrord-verifier" rel="noopener noreferrer"&gt;github.com/metalbear-co/holmes-mirrord-verifier&lt;/a&gt;. You'll need the &lt;a href="https://metalbear.com/mirrord/docs/operator/setup/installation" rel="noopener noreferrer"&gt;mirrord operator&lt;/a&gt; installed in your cluster.&lt;/p&gt;




&lt;p&gt;If you haven't read &lt;a href="https://metalbear.com/blog/ai-sre/" rel="noopener noreferrer"&gt;Part I&lt;/a&gt; yet, it has the recipe: the pattern, the verification code, and how to wire it into the AI-SRE you're already running.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mirrord: &lt;a href="https://metalbear.com/mirrord" rel="noopener noreferrer"&gt;https://metalbear.com/mirrord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Questions: &lt;a href="mailto:hi@metalbear.com"&gt;hi@metalbear.com&lt;/a&gt; · &lt;a href="https://metalbear.com/slack" rel="noopener noreferrer"&gt;https://metalbear.com/slack&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>sre</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Auto-verifying your AI-SRE's fixes against your real cluster, with mirrord</title>
      <dc:creator>Eyal Bukchin</dc:creator>
      <pubDate>Thu, 11 Jun 2026 11:02:50 +0000</pubDate>
      <link>https://dev.to/metalbear/auto-verifying-your-ai-sres-fixes-against-your-real-cluster-with-mirrord-2p16</link>
      <guid>https://dev.to/metalbear/auto-verifying-your-ai-sres-fixes-against-your-real-cluster-with-mirrord-2p16</guid>
      <description>&lt;p&gt;&lt;em&gt;Part I of two. Part II will be published next week, and will show the same loop end-to-end against HolmesGPT on a real cluster.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You're rolling out an AI-SRE (your own homegrown in-house AI loop, or one of the new products: Resolve AI, incident.io's Investigator, Datadog Bits). When an alert fires, it proposes a fix: a timeout here, a retry there, a config bump. The suggestion looks plausible. Do you merge it?&lt;/p&gt;

&lt;p&gt;Today, you read the diff, eyeball it against your mental model of the service, and decide, or you deploy to staging and wait. The bugs an AI-SRE gets paged on (an unhandled exception under a rare request shape, a downstream that times out for some requests, a webhook that races with itself, a slow query that only surfaces at scale) live in the gap between local and production. Unit tests and mocks don't reach there. Staging does, but staging is slow (a deploy on every iteration) and shared (you're competing with everyone else trying to reproduce their own bugs).&lt;/p&gt;

&lt;p&gt;This is where mirrord can help. mirrord runs a separate copy of your service as if it were a pod in your cluster, wired into the same real downstreams and upstreams without a deploy. This guide shows how to wire that into your AI-SRE so every suggested fix is verified against the real cluster before it reaches a human, automatically, in no time, with no SDK or code to import.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's an AI-SRE?
&lt;/h2&gt;

&lt;p&gt;A new category of tools that take the first investigative pass when an alert fires, before the on-call human is even awake. The AI-SRE pulls together the context a human would have spent the first ten minutes assembling (recent deploys, related logs, metric anomalies, runbooks, similar past incidents) and proposes a remediation. Most just produce suggestions; a human is still the one acting on them. A few are starting to auto-execute low-risk actions (pod restarts, config flag flips, even small auto-merged code patches).&lt;/p&gt;

&lt;p&gt;AI-SREs come in three flavors: standalone (Resolve AI, NeuBird, Cleric), AI bolted onto existing incident or observability tools (incident.io's Investigator, Datadog Bits, Rootly's Copilot, etc.), and homegrown LLM loops, which are the most common shape.&lt;/p&gt;

&lt;p&gt;Below are some examples of what an AI-SRE actually outputs. Every one of these is a fix that can't be verified without real cluster state, which is why this guide exists:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Alert&lt;/th&gt;
&lt;th&gt;AI-SRE's suggestion&lt;/th&gt;
&lt;th&gt;What verification has to prove&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Spike of &lt;code&gt;KeyError: 'address'&lt;/code&gt; in checkout handler&lt;/td&gt;
&lt;td&gt;Default the field to &lt;code&gt;None&lt;/code&gt; and guard the deref&lt;/td&gt;
&lt;td&gt;The previously-failing requests now return 2xx, no new errors introduced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Checkout p99 latency above SLO&lt;/td&gt;
&lt;td&gt;Add &lt;code&gt;timeout=300ms&lt;/code&gt; to the pricing-service call&lt;/td&gt;
&lt;td&gt;The slow outliers get cut off; p99 actually drops&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5xx burst after deploy&lt;/td&gt;
&lt;td&gt;Roll back commit &lt;code&gt;abc123&lt;/code&gt;, or guard the new code path with a feature flag&lt;/td&gt;
&lt;td&gt;The error rate stops climbing on real production traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhook handler creating duplicate orders&lt;/td&gt;
&lt;td&gt;Check idempotency key in Redis before insert&lt;/td&gt;
&lt;td&gt;A retried webhook produces one row, not two&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kafka consumer lag growing&lt;/td&gt;
&lt;td&gt;Bump &lt;code&gt;max.poll.records&lt;/code&gt;, add a backoff on a flaky downstream&lt;/td&gt;
&lt;td&gt;Lag actually drains, downstream stays healthy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;None of these can be verified with unit tests or mocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet &lt;code&gt;mirrord exec&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;mirrord exec&lt;/code&gt; runs a local process as if it were a pod in your cluster. Its outbound calls resolve through the target pod's network context, so when your patched code calls &lt;code&gt;payments&lt;/code&gt; or &lt;code&gt;inventory&lt;/code&gt; or your database, it hits the real in-cluster service. mirrord also routes incoming traffic to the local process when you ask it to. Environment variables, mounted ConfigMaps and Secrets, and the target's filesystem are inherited by default. This is what allows your AI-SRE to test the code fix it came up with instantly and without having to deploy to staging or production. The deployed pod is never touched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where mirrord fits
&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4iv5h65h2ng7mrhg2s7z.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%2F4iv5h65h2ng7mrhg2s7z.png" alt="AI-SRE verification loop" width="800" height="1014"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What your AI-SRE already owns
&lt;/h2&gt;

&lt;p&gt;This guide assumes three things about your AI-SRE: it (a) ingests an alert, (b) produces a candidate fix (a code diff, or a recommendation that needs a small bridge step to actually turn it into code, covered in Part II), and (c) has &lt;em&gt;some&lt;/em&gt; check for whether the bug is fixed (a repro script, a load test, the alerting query, or a known-good test case).&lt;/p&gt;

&lt;p&gt;mirrord doesn't replace any of these. It runs your patched service under &lt;code&gt;mirrord exec&lt;/code&gt;, so (c) can hit the real cluster, without a deploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to set it up
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Two things to install:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The mirrord &lt;strong&gt;operator&lt;/strong&gt; in your cluster (&lt;a href="https://metalbear.com/mirrord/docs/operator/setup/installation" rel="noopener noreferrer"&gt;install docs&lt;/a&gt;), one helm command.&lt;/li&gt;
&lt;li&gt;The mirrord &lt;strong&gt;CLI&lt;/strong&gt; wherever the AI-SRE will run the verification step: typically the AI-SRE's own worker, or a sidecar container alongside it (&lt;a href="https://metalbear.com/mirrord/docs/getting-started/quick-start" rel="noopener noreferrer"&gt;install docs&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Automated verification with &lt;code&gt;mirrord exec&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When the AI-SRE produces a candidate fix, run a short verification block from inside its own hook:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check out a working copy of the service code (&lt;code&gt;git clone&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Apply the AI-SRE's patch to it (&lt;code&gt;git apply patch.diff&lt;/code&gt;, or whatever your AI-SRE delivers)&lt;/li&gt;
&lt;li&gt;Run that patched copy under &lt;code&gt;mirrord exec&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;mirrord makes the local process behave as if it were the target pod (same network identity, same downstreams, same env), but the deployed service is untouched.&lt;/p&gt;

&lt;p&gt;Run it twice, once with the patch, once without. Both runs see the same live downstreams and upstreams, so the only variable is the patch.&lt;/p&gt;

&lt;p&gt;You'll want mirrord in &lt;strong&gt;steal mode with a header filter&lt;/strong&gt;, so the verifier diverts only its own tagged requests to the candidate and leaves production traffic alone. The mirrord config (write once, reuse per run):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.mirrord/verifier.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"feature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"network"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"incoming"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"steal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"http_filter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"header_filter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^X-Verifier-Run: {{ key }}$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"ports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;{{ key }}&lt;/code&gt; is a mirrord template variable that resolves to whatever you pass via &lt;code&gt;mirrord exec --key&lt;/code&gt;, so each verification run can tag itself uniquely without templating the config file.&lt;/p&gt;

&lt;p&gt;If your check is a &lt;strong&gt;repro script&lt;/strong&gt; that exits non-zero when the bug is present:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;RUN_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;uuidgen&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Start the candidate; mirrord will steal only requests tagged with $RUN_ID.&lt;/span&gt;
mirrord &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--config-file&lt;/span&gt; .mirrord/verifier.json &lt;span class="nt"&gt;--key&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RUN_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target&lt;/span&gt; deploy/&amp;lt;your-service&amp;gt; &lt;span class="nt"&gt;--&lt;/span&gt; ./service/run-server.sh &amp;amp;

&lt;span class="c"&gt;# Drive the repro at the real service URL, tagged with the header.&lt;/span&gt;
&lt;span class="c"&gt;# Other traffic to &amp;lt;your-service&amp;gt; keeps hitting the deployed pods.&lt;/span&gt;
./repro.sh https://&amp;lt;your-service&amp;gt;.svc.cluster.local &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"X-Verifier-Run: &lt;/span&gt;&lt;span class="nv"&gt;$RUN_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your check is &lt;strong&gt;metric-based&lt;/strong&gt; (latency or error rate, the common case for AI-SRE alerts), same shape, swap the repro for a load test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;RUN_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;uuidgen&lt;span class="si"&gt;)&lt;/span&gt;

mirrord &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--config-file&lt;/span&gt; .mirrord/verifier.json &lt;span class="nt"&gt;--key&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RUN_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target&lt;/span&gt; deploy/&amp;lt;your-service&amp;gt; &lt;span class="nt"&gt;--&lt;/span&gt; ./service/run-server.sh &amp;amp;

./loadtest.sh https://&amp;lt;your-service&amp;gt;.svc.cluster.local &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"X-Verifier-Run: &lt;/span&gt;&lt;span class="nv"&gt;$RUN_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; patched-metrics.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run that block once on the unpatched code and once on the patched one, diff &lt;code&gt;baseline-metrics.json&lt;/code&gt; vs &lt;code&gt;patched-metrics.json&lt;/code&gt;, and you have a verdict. The comparison is shaped by the alert: did the SLO condition the alert fires on still hold on the patched run? Plus a sanity check that the other signals didn't regress past tolerance. For an &lt;code&gt;error_rate &amp;gt; 5%&lt;/code&gt; alert, check the patched error rate is now under 5%, and that p50/p99 didn't grow past your tolerance. For a &lt;code&gt;p99 &amp;gt; 300ms&lt;/code&gt; alert, check p99 is now under 300ms, and that error rate didn't climb. (If your AI-SRE outputs a written report rather than ready-to-apply diffs, you'll also want a small bridge step; Part II walks through one.)&lt;/p&gt;

&lt;p&gt;An immediate verdict, against your real cluster. The verifier can also &lt;em&gt;reject&lt;/em&gt;. Sometimes the AI's fix moves the metric the alert fires on without moving it enough to clear the SLO, or improves one signal and regresses another. You want to find that out here, not in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wiring it into your AI-SRE
&lt;/h3&gt;

&lt;p&gt;The integration is light. Most AI-SREs already run a hook when they finalize a suggestion (the part that posts the PR comment or the Slack message). In that hook:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Apply the generated patch to a checked-out copy of the service.&lt;/li&gt;
&lt;li&gt;Run the verification block above. If it doesn't pass, post the comparison back to the AI-SRE so it can try again (per the diagram). The on-call human keeps working the original alert; they just don't review a fix that didn't survive verification.&lt;/li&gt;
&lt;li&gt;If it passes, post the verdict and the diff. A human (or your auto-merge policy) takes it from there.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One caveat on the REJECT-and-retry loop. Today's vendor AI-SREs (HolmesGPT, Resolve AI, incident.io's Investigator) are single-shot. To actually close the loop, put the retry in the small wrapper that turns the AI-SRE's recommendation into a code patch (covered in Part II): feed it the failed run's verdict and ask for another approach. Homegrown AI-SREs can put the retry wherever.&lt;/p&gt;

&lt;p&gt;In a noisy incident where your AI proposes ten patches, you spend ten quick verification runs and only the survivors reach a human.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus: hand humans a live preview (mirrord Enterprise)
&lt;/h3&gt;

&lt;p&gt;When verification passes and a human still wants to click around before merging, mirrord preview environments (an Enterprise-tier operator feature) give them an isolated pod from the patched image, reachable at the same service URL with a session header.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mirrord preview start &lt;span class="nt"&gt;--key&lt;/span&gt; fix-&lt;span class="nv"&gt;$INCIDENT_ID&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; registry.example.com/&amp;lt;your-service&amp;gt;:fix-&lt;span class="nv"&gt;$INCIDENT_ID&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target&lt;/span&gt; deployment/&amp;lt;your-service&amp;gt; &lt;span class="nt"&gt;--ttl&lt;/span&gt; 30

curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'baggage: mirrord-session=fix-$INCIDENT_ID'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://&amp;lt;your-service&amp;gt;.prod.svc/...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other traffic keeps hitting the unpatched pods; the header is what routes you to the candidate. After the TTL the operator tears it down. See the &lt;a href="https://metalbear.com/mirrord/docs/use-cases/preview-environments" rel="noopener noreferrer"&gt;preview environments docs&lt;/a&gt; for details.&lt;/p&gt;




&lt;p&gt;That's the recipe. &lt;strong&gt;Part II&lt;/strong&gt; (coming next week) shows the loop running end-to-end against HolmesGPT, an OSS AI-SRE that ships standalone. Two planted bugs in a real GKE cluster: one the loop signs off on, one the loop correctly rejects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just stage a copy of the service?
&lt;/h2&gt;

&lt;p&gt;You could run a copy of &lt;code&gt;checkout&lt;/code&gt; in a separate namespace, point it at the real &lt;code&gt;pricing&lt;/code&gt;, and call that verification. The reasons &lt;code&gt;mirrord exec&lt;/code&gt; is a better fit specifically for &lt;em&gt;AI-SRE auto-verification&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity matches prod.&lt;/strong&gt; &lt;code&gt;mirrord exec&lt;/code&gt; inherits the target pod's ServiceAccount, OIDC token, and service-mesh identity. A staged copy gets its own. The bugs AI-SREs handle often involve auth, mTLS, or NetworkPolicy interactions where identity is the variable; if your verification runs as a different principal than prod, you can pass on a fix that prod would still reject.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Env, secrets, mounts inherited automatically.&lt;/strong&gt; mirrord pulls the target pod's environment variables, mounted ConfigMaps and Secrets, and filesystem. Staged copies need a parallel set kept in sync; drift = false verdict. AI-SRE patches frequently touch env-shaped behavior (a missing flag, a stale config), which is exactly the drift class you want verification to catch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seconds, not minutes.&lt;/strong&gt; &lt;code&gt;mirrord exec&lt;/code&gt; runs from a checked-out working copy in a few seconds. The staged-namespace approach is build image, push, &lt;code&gt;kubectl apply&lt;/code&gt;, wait-ready, port-forward, several minutes per try. In a noisy incident where the AI tries ten patches, that's the difference between "all ten verified in under five minutes" and "one verification per coffee."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel runs are free.&lt;/strong&gt; Each &lt;code&gt;mirrord exec&lt;/code&gt; is its own process. Ten candidate patches can verify concurrently. The staged-copy approach shares a Deployment, Service, and Ingress, so concurrent runs collide unless you also templatize per-run namespaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Setup against any cluster you can &lt;code&gt;kubectl&lt;/code&gt; into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install the CLI&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;metalbear-co/mirrord/mirrord

&lt;span class="c"&gt;# install the operator in your cluster (Prerequisites above)&lt;/span&gt;

&lt;span class="c"&gt;# pick any deployment and confirm the loop works&lt;/span&gt;
mirrord &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--target&lt;/span&gt; deploy/&amp;lt;your-service&amp;gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;printenv&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If that prints env vars from the target pod (not your local shell's), the verification primitive is live. Wire your AI-SRE's post-suggestion hook to the pattern in &lt;em&gt;Automated verification&lt;/em&gt; above and let the next alert prove itself. Then read Part II (coming next week) for the full walkthrough against HolmesGPT.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mirrord: &lt;a href="https://metalbear.com/mirrord" rel="noopener noreferrer"&gt;https://metalbear.com/mirrord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Questions: &lt;a href="mailto:hi@metalbear.com"&gt;hi@metalbear.com&lt;/a&gt; · &lt;a href="https://metalbear.com/slack" rel="noopener noreferrer"&gt;https://metalbear.com/slack&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>sre</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Six Claude Code Skills That Close the AI Agent Feedback Loop</title>
      <dc:creator>Eyal Bukchin</dc:creator>
      <pubDate>Wed, 13 May 2026 16:56:14 +0000</pubDate>
      <link>https://dev.to/metalbear/six-claude-code-skills-that-close-the-ai-agent-feedback-loop-10bb</link>
      <guid>https://dev.to/metalbear/six-claude-code-skills-that-close-the-ai-agent-feedback-loop-10bb</guid>
      <description>&lt;p&gt;AI agents write code that compiles, runs locally, and breaks the first time it touches your Kubernetes cluster. The cluster is full of state the model never sees: the env vars on the running pod, the schema in your real Postgres, the headers your upstream &lt;code&gt;auth-service&lt;/code&gt; sends, the topics your consumer subscribes to. Without that context, the code an agent writes for your live infrastructure is informed guessing, whether you're shipping a new feature or fixing a regression.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metalbear.com/mirrord/" rel="noopener noreferrer"&gt;mirrord&lt;/a&gt; closes that gap. It runs a local process as if it were a real pod inside your cluster: real env vars, real DNS, real network, optionally real inbound traffic. A real example: &lt;a href="https://metalbear.com/mirrord/case-study/daylight/" rel="noopener noreferrer"&gt;Daylight Security&lt;/a&gt; pairs Cursor with mirrord for daily development. Their team cut their typical edit-test cycle from 5–8 minutes to about 5 seconds. The reason isn't faster CPUs; it's that the agent now operates against the real cluster the way a senior engineer would, instead of guessing from logs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We recently shipped six &lt;a href="https://agentskills.io" rel="noopener noreferrer"&gt;Agent Skills&lt;/a&gt; that teach AI agents how and when to use mirrord. The whole bundle installs in one command.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Claude Code&lt;/span&gt;
/plugin marketplace add metalbear-co/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Any Agent Skills consumer&lt;/span&gt;
npx skills add metalbear-co/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what each skill does, with a concrete prompt that triggers it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;code&gt;mirrord-quickstart&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Zero-to-first-session for engineers (and agents) who have never used mirrord. Detects your OS, walks through CLI install or VS Code / IntelliJ setup, finds your target pod in the cluster, runs your first session. Your local process can now reach every service, database, and queue in the cluster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "I'm new to mirrord, help me run my Node app against my staging cluster."&lt;/p&gt;

&lt;p&gt;The agent installs mirrord, lists targets in your namespace, picks a likely match, and runs &lt;code&gt;mirrord exec --target … -- node server.js&lt;/code&gt;. No copy-paste from docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;code&gt;mirrord-config&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Generates and validates &lt;code&gt;mirrord.json&lt;/code&gt;, which tells mirrord what to do and where to do it. mirrord's config surface is wide: traffic stealing vs mirroring, filesystem modes, env injection, target selection, database and queue behavior. The skill turns "I want X behavior" into valid config without you opening the docs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "Steal traffic from &lt;code&gt;pod/api-server&lt;/code&gt;, but only requests carrying my baggage header so I don't break anyone else's session."&lt;/p&gt;

&lt;p&gt;The agent writes the right config, validates it against the schema, and explains what it does. The interesting part: the skill covers the full &lt;code&gt;mirrord.json&lt;/code&gt; surface (target selection, traffic modes, env injection, file system hooks), not just filters. Filtered steal is one of the things that lets multiple developers share one cluster without colliding, but it's only one of the patterns mirrord-config knows how to set up.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;code&gt;mirrord-operator&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Sets up the &lt;a href="https://metalbear.com/mirrord/docs/" rel="noopener noreferrer"&gt;mirrord Operator&lt;/a&gt; for teams. Mirroring traffic from a pod is concurrency-safe out of the box; you only need the operator when multiple developers want to &lt;em&gt;steal&lt;/em&gt; the same pod's traffic with different filters, share branched databases, or split a Kafka topic. The operator brokers session boundaries, RBAC, and the routing rules that make those interactions work without collisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "Install the operator on our EKS cluster and configure RBAC so only the &lt;code&gt;dev&lt;/code&gt; group can use it."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://monday.com" rel="noopener noreferrer"&gt;monday.com&lt;/a&gt; runs 350+ engineers on a single shared staging cluster this way. The operator is what makes that scale work: concurrent filtered steal so multiple devs share one pod, queue splitting so they share one SQS topic, DB branching so they share one database, RBAC so they don't touch workloads they shouldn't, and the rest of the routing rules that let 350 developers work on the same cluster at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;code&gt;mirrord-ci&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Run integration tests in CI in isolation against your staging cluster, instead of spinning up an ephemeral test environment for each PR. The service under test runs in the CI runner with mirrord; mirrord steals the cluster traffic destined for it and routes it to your build, so test traffic follows the same path it would in production, with only that one service swapped. That catches the integration bugs mocks miss, with one shared staging cluster instead of one ephemeral cluster per PR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "Set up GitHub Actions to run our integration tests against the staging cluster."&lt;/p&gt;

&lt;p&gt;The agent writes the workflow, injects your kubeconfig from a secret, sets &lt;code&gt;MIRRORD_CI_API_KEY&lt;/code&gt;, and wires &lt;code&gt;mirrord ci start&lt;/code&gt; around your service and &lt;code&gt;mirrord ci stop&lt;/code&gt; in the cleanup hook.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;code&gt;mirrord-db-branching&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Per-developer database branches. Copy-on-write Postgres (or &lt;a href="https://metalbear.com/mirrord/docs/sharing-the-cluster/db-branching" rel="noopener noreferrer"&gt;any supported DB&lt;/a&gt;), so two engineers can develop against "the same" database without stepping on each other's writes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "Give me an isolated DB branch off the staging Postgres for this feature."&lt;/p&gt;

&lt;p&gt;The agent provisions the branch via the operator, points your local process at the branch, and tears down when the session ends. No more "who deleted the test users?" Slack threads.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;code&gt;mirrord-kafka&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Kafka queue splitting. Each developer gets a slice of the topic that only they consume, while the original consumer keeps running in the cluster. Lets you run a real Kafka workload locally without intercepting messages other people care about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt; "Set up queue splitting on the &lt;code&gt;orders.created&lt;/code&gt; topic for my local consumer."&lt;/p&gt;

&lt;p&gt;The agent configures the operator's Kafka splitter, gives your local process a per-developer consumer group, and confirms message routing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Claude Code&lt;/span&gt;
/plugin marketplace add metalbear-co/skills

&lt;span class="c"&gt;# Any Agent Skills consumer&lt;/span&gt;
npx skills add metalbear-co/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;a href="https://github.com/metalbear-co/skills" rel="noopener noreferrer"&gt;github.com/metalbear-co/skills&lt;/a&gt;. Issues and PRs welcome; we ship updates fast.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>ai</category>
      <category>claude</category>
      <category>devops</category>
    </item>
    <item>
      <title>mirrord as an alternative to Telepresence</title>
      <dc:creator>Eyal Bukchin</dc:creator>
      <pubDate>Fri, 11 Aug 2023 09:50:22 +0000</pubDate>
      <link>https://dev.to/eyalb/mirrord-as-an-alternative-to-telepresence-39mn</link>
      <guid>https://dev.to/eyalb/mirrord-as-an-alternative-to-telepresence-39mn</guid>
      <description>&lt;p&gt;A question that comes up often from those already familiar with local Kubernetes development is how mirrord compares to Telepresence. The idea at the base of both products is indeed similar: instead of deploying your new code to the cloud and testing it there, connect it to the cloud from your local machine. By shifting left on cloud testing this way you utilize your cloud environment much more effectively and speed up your development process. The people at Ambassador Labs &lt;a href="https://www.getambassador.io/docs/telepresence-oss/latest/concepts/devworkflow" rel="noopener noreferrer"&gt;wrote about it at length&lt;/a&gt;.&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%2Fewa9vla8w465jz4v6yp2.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%2Fewa9vla8w465jz4v6yp2.png" alt="The mandatory mirrord VS. Telepresence image" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, the technical approach at the base of mirrord is very different from that of Telepresence, which translates into significant differences in usability, compatibility, and performance. What Telepresence does is install an operator in your cluster, then connect you to the cluster via VPN (either your entire development machine or a containerized subset). On the other hand, this is what happens when you run a local process with mirrord:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;mirrord starts a pod (called the mirrord agent) on the same network namespace as your target. This pod is cleaned up automatically at the end of execution.&lt;/li&gt;
&lt;li&gt;mirrord then injects itself into your process, overrides low-level functions and relays them to the mirrord agent, who then executes them on the target in the cluster and sends back the results. For example, when your process tries to read a file, mirrord intercepts that function call and instead asks the agent to read that file from the remote target. mirrord does this for everything - traffic, file operations, environment variables - so your process behaves as if it was executed within the Kubernetes cluster, and with the entire context of your target.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s pretty heavy lifting compared to just starting a VPN - mirrord has to hook and reimplement a lot of functions for everything to work smoothly across different frameworks. But there’s a payoff:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;By providing your local process with the &lt;strong&gt;entire remote context of the pod&lt;/strong&gt; you chose to target, mirrord &lt;strong&gt;natively supports complex flows&lt;/strong&gt;. For example, if when your process receives a request it queries a database - since mirrord provides it with the pod’s environment variables and files, it’s going to have the necessary credentials, and since mirrord intercepts the outgoing requests and sends it out from the remote pod instead, it won’t be interrupted by any network rules blocking access from outside of the cluster. &lt;/li&gt;
&lt;li&gt;mirrord &lt;strong&gt;doesn’t need root access&lt;/strong&gt; on your machine. All it does is override the functions of a running process; the rest of your machine remains untouched&lt;/li&gt;
&lt;li&gt;You &lt;strong&gt;don’t have to install anything on your cluster&lt;/strong&gt; - mirrord uses the Kubernetes API, so all you need is a configured kubeconfig. mirrord does create a pod when it runs, but it cleans itself up at the end of execution.&lt;/li&gt;
&lt;li&gt;As you might have guessed, mirrord &lt;strong&gt;supports traffic mirroring&lt;/strong&gt;. It can still intercept traffic like Telepresence does, but if you want to leave the remote process completely untouched, mirrord can also just duplicate its traffic and send a copy to you. The original requests are handled by the remote service, so people accessing it are completely unaware that you’re using mirrord to debug it.&lt;/li&gt;
&lt;li&gt;As opposed to Telepresence which works at the network level, mirrord works at the pod level. This means it also &lt;strong&gt;supports pods that aren’t exposed through a service&lt;/strong&gt;, and gives your local code access to anything the pod can access, including &lt;strong&gt;components outside the cluster&lt;/strong&gt;. It also natively supports environments with service mesh like Linkerd or Istio.&lt;/li&gt;
&lt;li&gt;Because the mirrord client works at the process level, you can easily &lt;strong&gt;configure exactly what’s executed remotely and what stays local&lt;/strong&gt;. For example, you could make all the components of the remote cluster accessible to your local process, but have it write to the database locally; or have it read files from the local file system, except a few specific files that you want to get from the remote pod. &lt;/li&gt;
&lt;li&gt;mirrord is a tool for developers, and as such, in addition to a CLI tool, it also comes as an &lt;strong&gt;IDE plugin for both VS Code and the IntelliJ IDEs&lt;/strong&gt;. This is the most popular way to use mirrord, where it naturally fits into the existing development workflow.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most importantly though, all of these things are supported out of the box and with no required changes to your system. You don’t have to set up mounts, manually ingest environment variables, or create headless services. Just run your process with mirrord, and everything works. It’s this lack of friction that really makes the vision of local Kubernetes development possible - a true shift left of the cloud, where running your code in Kubernetes isn’t the thing you’re saving for last after all the unit tests and local setups, but rather the first thing you do when you write new code. &lt;/p&gt;

&lt;p&gt;Usage is simple and intuitive. In the CLI:&lt;br&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%2Fzbgcqrqrxui6iwa5sbsc.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%2Fzbgcqrqrxui6iwa5sbsc.png" alt="A very straightforward breakdown of the mirrord CLI command" width="799" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And in the IDE - enable mirrord, run or debug your code, and select a target. For example, in VSCode:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl18ffrxg2xxs1akqhpnf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl18ffrxg2xxs1akqhpnf.gif" alt="Quick demo of mirrord being used within VS Code" width="760" height="713"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it out!
&lt;/h2&gt;

&lt;p&gt;If you want to take mirrord for a spin, check out the &lt;a href="https://mirrord.dev/docs/overview/quick-start/" rel="noopener noreferrer"&gt;quick start guide&lt;/a&gt;. We’d love to hear about your experience or just general thoughts - chat us up on our &lt;a href="https://discord.gg/metalbear" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; or open an issue or discussion on &lt;a href="https://github.com/metalbear-co/mirrord" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>tooling</category>
      <category>development</category>
    </item>
    <item>
      <title>Approaches in Cloud Development Ergonomics</title>
      <dc:creator>Eyal Bukchin</dc:creator>
      <pubDate>Tue, 15 Nov 2022 15:47:30 +0000</pubDate>
      <link>https://dev.to/eyalb/approaches-in-cloud-development-ergonomics-5967</link>
      <guid>https://dev.to/eyalb/approaches-in-cloud-development-ergonomics-5967</guid>
      <description>&lt;p&gt;The advent of microservice architectures and cloud-native has taken some pretty severe tolls on developer ergonomics. It feels as if the tools cloud developers have at their disposal haven’t evolved fast enough to keep up with the rapid progress in infrastructure, and this tool debt is readily apparent in the day-to-day of the modern developer. &lt;/p&gt;

&lt;p&gt;The clearest example of this is that it’s now &lt;strong&gt;really hard to just run your application&lt;/strong&gt;. Not the one microservice you’re currently working on, but your actual entire application, which you ultimately deploy to the cloud and serves your customers. You used to be able to fire up your monolith right there on your laptop from within your IDE (crash, change some code, run it again), but architectures today have become resource-intensive, reliant on third-party services, and mostly just plain convoluted to the point where local execution is no longer a viable option.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frt2tydvq4rg1kufzdx58.jpg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frt2tydvq4rg1kufzdx58.jpg" alt="Ergonomics" width="687" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we talk about something as elementary as running your application, it naturally applies to many aspects of the developer’s day-to-day: debugging, testing, even just writing new code to see if it works. Therefore, solutions that make your application even a little easier to run provide significant value, just by affecting so many routine activities.&lt;br&gt;
In this article, we’re going to discuss today’s dominant approaches to making microservice applications easier for developers to run, and we’re also going to make the case for our &lt;a href="https://mirrord.dev" rel="noopener noreferrer"&gt;own thing&lt;/a&gt; - namely, a single shared environment in the cloud that the organization maintains, and that developers can plug in and out of non-intrusively as they develop their microservices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contemporary Cloud Development Workflows
&lt;/h2&gt;

&lt;p&gt;In the frictionless microservice utopia, the development workflow goes something along these lines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Microservices are independent and new functionality can be developed one microservice at a time &lt;/li&gt;
&lt;li&gt;Microservices talk to each other via well-defined contracts which can be tested in isolation&lt;/li&gt;
&lt;li&gt;Databases, queues, and third-party services consumed by a microservice also expose a consistent and well-defined contract, and as such can be mocked for testing purposes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, a service can be tested on its own, and then deployed to the production environment where it would play nicely with all the other components.&lt;/p&gt;

&lt;p&gt;However, let's assume you’re a microservice developer who doesn’t work in an organization where everyone designs perfect contracts and writes rigorous tests (or they do, but the third-party managed services you rely on don’t). When writing new code, you probably make as much progress as you can within the scope of the one or two microservices you’re working on at the moment, but then you do one or more of the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wrangle your entire application - microservices, databases and all - to run on your local machine&lt;/li&gt;
&lt;li&gt;Deploy your new code to a personal persistent/ephemeral development environment in the cloud &lt;/li&gt;
&lt;li&gt;Deploy your new code to a shared staging environment and test it there&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Run Locally
&lt;/h3&gt;

&lt;p&gt;This approach works great when it’s feasible, which is usually at a very early stage in the life of the application where it’s still small and tenable. There’s some tooling that lets you extend this honeymoon phase by letting you do it more easily, like &lt;a href="https://docs.docker.com/compose" rel="noopener noreferrer"&gt;docker-compose&lt;/a&gt;, &lt;a href="https://skaffold.dev" rel="noopener noreferrer"&gt;Skaffold&lt;/a&gt;, or &lt;a href="https://tilt.dev" rel="noopener noreferrer"&gt;Tilt&lt;/a&gt;. However, at a certain point, even if you’ve written whatever scriptage is needed to actually configure and run the latest stable version of all of your components together, you’re going to hit some sort of ceiling: if you’ve got a large database, or some CPU-heavy computations, or you’re relying on some managed service that can’t be containerized, this approach soon becomes untenable.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwbgrte0ckginj713ym6n.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwbgrte0ckginj713ym6n.png" alt="Local Environment" width="469" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Convenient development on your local machine&lt;/li&gt;
&lt;li&gt;No reliance on network or external services&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Difficult/impossible for large applications (ones with e.g. many microservices, a large database, high bandwidth usage)&lt;/li&gt;
&lt;li&gt;Doesn’t support hard-to-containerize components, like managed services&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Personal Cloud Environment
&lt;/h3&gt;

&lt;p&gt;With Infrastructure as Code at its current state of maturity, it’s now easier than ever to replicate microservice environments in the cloud. This unlocked a new approach of having a personal production-like cloud environment for every developer, which they can use freely and in isolation. It comes in two flavors - persistent environments, or ephemeral environments created on demand with products like &lt;a href="https://okteto.com" rel="noopener noreferrer"&gt;Okteto&lt;/a&gt; or &lt;a href="https://bunnyshell.com" rel="noopener noreferrer"&gt;Bunnyshell&lt;/a&gt; (also sometimes called Environment as a Service)&lt;sup id="fnref1"&gt;1&lt;/sup&gt;. This approach overcomes the resource limitations of the local environment but substitutes them for some new difficulties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For persistent environments, cost (determined by the size of the environment times the number of developers) becomes a factor. As the company grows, so do its architecture and the number of developers, leading to soaring cloud bills&lt;/li&gt;
&lt;li&gt;To generate state, database seed files are used. These need to be maintained so they don’t become stale&lt;/li&gt;
&lt;li&gt;You have to work against a cloud environment, which isn’t always fun (though some tools make it easier, like &lt;a href="https://github.com/features/codespaces" rel="noopener noreferrer"&gt;GitHub Codespaces&lt;/a&gt; or &lt;a href="https://www.gitpod.io/" rel="noopener noreferrer"&gt;Gitpod&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Same as with running your application locally, having hard-to-containerize components in your architecture like managed services can make this approach unfeasible.&lt;/li&gt;
&lt;/ul&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F53qmw9znqkoy063lc91x.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F53qmw9znqkoy063lc91x.png" alt="Personal Environment" width="688" height="742"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Not capped by the hardware limitations of your development machine&lt;/li&gt;
&lt;li&gt;Better simulation of your production environment&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;No production-like database state&lt;/li&gt;
&lt;li&gt;Local changes have to be synced to the cloud&lt;/li&gt;
&lt;li&gt;Doesn’t support hard-to-containerize components, like managed services&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Shared Cloud Environment
&lt;/h3&gt;

&lt;p&gt;A lot of organizations have already put in the effort of setting up a single, shared production-like environment for testing - the staging environment. It’s persistent and has already been set up manually to include all components, including third-party services, databases with full state (some companies even automatically stream data from production), and all the microservices. In terms of simulating production, it’s hard to do much better.&lt;/p&gt;

&lt;p&gt;However, since this environment is shared by multiple developers, some measures are usually in place to keep it stable - for example, you can only actually deploy new code through the CI, often meaning you have to wait for a code review and your entire suite of automated tests to run (not to mention the deployment script itself) before it actually gets there. Even then, the tests aren’t perfect, and sometimes you end up deploying broken code and corrupting the environment, much to the chagrin of your fellow developers.&lt;/p&gt;

&lt;p&gt;This is where shared environment tools like &lt;a href="https://telepresence.io/" rel="noopener noreferrer"&gt;Telepresence&lt;/a&gt; and &lt;a href="https://www.codezero.io/" rel="noopener noreferrer"&gt;CodeZero&lt;/a&gt; can help. They assume you're only working on one or two microservices anyway, and running them locally is not an issue. These tools let you connect your local service to the staging environment, replacing the service currently running in the cluster, without deployment. The code you're working on runs locally, and its dependencies run in the cloud. Not only can you keep working on your local environment, you can iterate on testing against your cloud environment without waiting for lengthy CI and deployment processes.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw49mgxgd2px4698xjtck.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw49mgxgd2px4698xjtck.png" alt="Shared Environment" width="800" height="699"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Leverage a single shared environment, making it feasible for you to manually set up database state and managed services (since you only have to do it once, for one environment)&lt;/li&gt;
&lt;li&gt;You can still work locally within your IDE&lt;/li&gt;
&lt;li&gt;Code changes happen locally, so iterations are fast (no need to deploy to the cloud)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;One developer can break the environment for the others&lt;/li&gt;
&lt;li&gt;If the environment is corrupted, it’s hard to recover&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Sell
&lt;/h2&gt;

&lt;p&gt;So local setups are easy to use but don’t support large deployments; personal cloud environments support large deployments but don’t really reflect production, don’t support components that can’t be containerized, and cost a lot; and shared environments reflect production for cheap, but don’t really support concurrency without sacrificing stability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mirrord.dev" rel="noopener noreferrer"&gt;mirrord&lt;/a&gt; lets you have all of these cakes and eat them too. We essentially took the shared environment approach and tacked on isolation. We do this by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Letting developers mirror incoming traffic rather than just intercept it. This lets multiple developers work on the same service in the cloud, while the service is still running and handling requests.&lt;/li&gt;
&lt;li&gt;Giving developers fine-grained control over what happens locally and what happens remotely. This way, for example, incoming traffic mirroring and file reads can happen remotely, but outgoing traffic and file writes can be local. Future versions of mirrord will include more advanced modes of configuration, letting users filter by e.g. hostname or protocol.&lt;/li&gt;
&lt;li&gt;In future versions, supporting advanced features like copy-on-write for databases.&lt;/li&gt;
&lt;li&gt;In our upcoming cloud solution, providing RBAC, letting the organization control which teams have access to which parts of the staging environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using mirrord, developers can run the one service they’re working on locally, without juggling configurations or straining their development machine; they can run it against a full environment with mature database state and managed services; and they can do it quickly, easily and without risk. &lt;/p&gt;

&lt;p&gt;We’ve recently released our &lt;a href="https://metalbear.co/blog/mirrord-3.0-is-out/" rel="noopener noreferrer"&gt;first stable version&lt;/a&gt;, and would love to hear your thoughts (on &lt;a href="https://github.com/metalbear-co/mirrord" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; or &lt;a href="https://discord.gg/pSKEdmNZcK" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;).&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;It can also be supplemented with a cloud development environment, as provided by products like Gitpod or Codespaces. For a comprehensive survey of the non-localhost space see this &lt;a href="https://dx.tips/the-end-of-localhost" rel="noopener noreferrer"&gt;excellent article&lt;/a&gt;.  &amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>productivity</category>
      <category>cloudnative</category>
      <category>microservices</category>
      <category>programming</category>
    </item>
    <item>
      <title>(Re)Introducing mirrord (or: the War on the Long Dev Loop)</title>
      <dc:creator>Eyal Bukchin</dc:creator>
      <pubDate>Tue, 31 May 2022 09:12:57 +0000</pubDate>
      <link>https://dev.to/eyalb/reintroducing-mirrord-or-the-war-on-the-long-dev-loop-nil</link>
      <guid>https://dev.to/eyalb/reintroducing-mirrord-or-the-war-on-the-long-dev-loop-nil</guid>
      <description>&lt;p&gt;Originally posted on the &lt;a href="https://metalbear.co/blog/reintroducing-mirrord/" rel="noopener noreferrer"&gt;MetalBear blog&lt;/a&gt;.&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%2F0g92u051f0vdd9933kx6.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%2F0g92u051f0vdd9933kx6.png" alt="mirrord logo" width="446" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dev Loop (or: know your enemy)
&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifc7f9wh8azjdoa65j7g.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%2Fifc7f9wh8azjdoa65j7g.png" alt="The dev loop" width="241" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine you’re a backend developer at post series B SaaS soonicorn. You’ve spent half a sprint adding a new feature to your microservice. You’ve thoroughly researched possible inputs and database states and built an elaborate test suite. Your code was mercilessly reviewed by two of your teammates. Finally, the tests pass, the pull request is approved, and as a final verification, you deploy your new code to the staging environment…&lt;/p&gt;

&lt;p&gt;Where it crashes almost immediately. Turns out you forgot to test some obscure configuration, or some complex database state that would only ever occur on a mature, complex environment - like staging, and unlike your local machine.&lt;br&gt;
So you roll the service back on staging, fix the bug, write some more tests, get it reviewed again, build the code, deploy it to staging… and it crashes again. While you were fixing the bug, your teammate deployed a new version of some other microservice - except they're not as thorough a tester as you are, and the new version is broken, so you can’t test your own service. You wait for them to roll their service back to a working version, the sprint is long over, and you’ve started on your next feature during your downtime so now you’re dividing your focus between two things.&lt;/p&gt;

&lt;p&gt;The worst part being that you know it’s going to happen again next sprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  mirrord (or: how you win)
&lt;/h2&gt;

&lt;p&gt;I’ve encountered some variation of the dev loop at every startup I’ve ever worked in, and it’s this pain exactly that we’re trying to solve with mirrord. mirrord runs in two places - on your local development machine, and in your staging environment. By wrapping your local process and hooking system calls, it lets you plug your process non-invasively into that service’s instance on the staging environment. &lt;br&gt;
Simply put, mirrord lets you run a local process in the context of your cloud service. This means you can test your code on staging, without actually deploying it there. Not only does it save you the hassle of deployment every time you make a change, but it also keeps the staging environment free from untested versions, and constantly usable for everyone else in the organization.&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%2Fdt51lnzabke5phsh35or.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%2Fdt51lnzabke5phsh35or.png" alt="mirrord architecture" width="800" height="477"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started (and: other practical info)
&lt;/h2&gt;

&lt;p&gt;Today we’re releasing &lt;a href="https://mirrord.dev" rel="noopener noreferrer"&gt;mirrord 2.0&lt;/a&gt;, which supports incoming traffic. That means whatever traffic reaches your service in staging is duplicated by mirrord and sent to your local process. We’ll soon be adding support for outgoing traffic, file access, and environment variables - everything needed for your local process to “think” it’s running on the staging environment.&lt;br&gt;
All you need to run mirrord is kubectl access to your staging environment&lt;sup id="fnref1"&gt;1&lt;/sup&gt;. You can use it as either a CLI tool, or an extension for VS Code (IntelliJ support is on the way). Try it out &lt;a href="https://mirrord.dev" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and let us know what you think at &lt;a href="mailto:hi@metalbear.co"&gt;hi@metalbear.co&lt;/a&gt;, or in our repo!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;note that mirrord doesn’t install anything persistent in your Kubernetes cluster. It runs a job that self-deletes when mirrord terminates.&amp;nbsp;↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
