<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>0xE8 - Blog</title>
    <subtitle>0xE8 is a software engineering consultancy: process audits, reliability practices, AI deployment, and systems architecture.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://0xe8.com/blog/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://0xe8.com/blog/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-02-18T00:00:00+00:00</updated>
    <id>https://0xe8.com/blog/atom.xml</id>
    <entry xml:lang="en">
        <title>Cutting deploy cost by a third without adding a single dashboard</title>
        <published>2026-02-18T00:00:00+00:00</published>
        <updated>2026-02-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            Geronimo GS
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://0xe8.com/blog/cutting-deploy-cost-without-a-dashboard/"/>
        <id>https://0xe8.com/blog/cutting-deploy-cost-without-a-dashboard/</id>
        
        <content type="html" xml:base="https://0xe8.com/blog/cutting-deploy-cost-without-a-dashboard/">&lt;p&gt;A platform org of about ninety engineers came to us with a familiar complaint: releases used to take a day, now they take most of a week, and nobody could point to exactly why. Headcount had roughly doubled in eighteen months. Deploy frequency hadn&#39;t moved.&lt;/p&gt;
&lt;p&gt;We ran our usual two-week diagnostic: trace an actual change from ticket to production, write down every wait, every handoff, every manual step. Not the pipeline in the wiki — the one engineers actually route through when the wiki&#39;s version is slower than asking someone directly in Slack.&lt;/p&gt;
&lt;h2 id=&quot;what-we-expected-to-find&quot;&gt;What we expected to find&lt;/h2&gt;
&lt;p&gt;Going in, the obvious suspect was the CI pipeline itself. Slow test suites, flaky infrastructure, that kind of thing. It&#39;s usually where teams look first, because it&#39;s the part they can see.&lt;/p&gt;
&lt;h2 id=&quot;what-we-actually-found&quot;&gt;What we actually found&lt;/h2&gt;
&lt;p&gt;The pipeline was fine. Fifteen minutes, mostly test execution, nothing embarrassing. The other four days and change were almost entirely queueing: waiting for one of two people who understood a particular legacy service well enough to approve changes to it, waiting for a weekly change-advisory meeting that had quietly become mandatory for anything touching billing, waiting for a staging environment that was shared across six teams and perpetually in a broken state left by whoever used it last.&lt;/p&gt;
&lt;p&gt;None of this showed up in any dashboard, because none of it was a system anyone was measuring. It was organizational scar tissue — reasonable decisions made individually, two years&#39; worth of them, that added up to a four-day queue nobody had designed on purpose. Laid out by hours actually spent, the pipeline is barely visible:&lt;/p&gt;
&lt;div class=&quot;bar-chart&quot; style=&quot;--accent: #A24BF5&quot;&gt;
  &lt;div class=&quot;bar-row&quot;&gt;
    &lt;div class=&quot;bar-row-label&quot;&gt;CI pipeline&lt;/div&gt;
    &lt;div class=&quot;bar-track&quot;&gt;&lt;div class=&quot;bar-fill&quot; style=&quot;width: 0.5813953488372093%;&quot;&gt;&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;bar-row-value&quot;&gt;0.25 hrs&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;bar-row&quot;&gt;
    &lt;div class=&quot;bar-row-label&quot;&gt;Shared staging conflicts&lt;/div&gt;
    &lt;div class=&quot;bar-track&quot;&gt;&lt;div class=&quot;bar-fill&quot; style=&quot;width: 51.162790697674424%;&quot;&gt;&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;bar-row-value&quot;&gt;22 hrs&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;bar-row&quot;&gt;
    &lt;div class=&quot;bar-row-label&quot;&gt;Legacy-service approval wait&lt;/div&gt;
    &lt;div class=&quot;bar-track&quot;&gt;&lt;div class=&quot;bar-fill&quot; style=&quot;width: 83.72093023255815%;&quot;&gt;&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;bar-row-value&quot;&gt;36 hrs&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;bar-row&quot;&gt;
    &lt;div class=&quot;bar-row-label&quot;&gt;Change-advisory meeting&lt;/div&gt;
    &lt;div class=&quot;bar-track&quot;&gt;&lt;div class=&quot;bar-fill&quot; style=&quot;width: 100.0%;&quot;&gt;&lt;/div&gt;&lt;/div&gt;
    &lt;div class=&quot;bar-row-value&quot;&gt;43 hrs&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2 id=&quot;what-we-changed&quot;&gt;What we changed&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Split the legacy-service approval bottleneck into a documented ownership boundary with a second trained approver, cutting median wait from a day and a half to under two hours.&lt;/li&gt;
&lt;li&gt;Replaced the blanket change-advisory meeting with an actual risk classification, so only the changes that needed a human review before shipping got one.&lt;/li&gt;
&lt;li&gt;Gave each team its own disposable staging environment instead of a shared one, which also — as a side effect nobody asked for — cut a class of &quot;worked on staging, broke in prod&quot; incidents to roughly zero.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;where-it-landed&quot;&gt;Where it landed&lt;/h2&gt;
&lt;div class=&quot;stat-row&quot;&gt;
&lt;div class=&quot;stat-tile&quot; style=&quot;--accent: #A24BF5&quot;&gt;
  &lt;div class=&quot;stat-value&quot;&gt;38%&lt;/div&gt;
  &lt;div class=&quot;stat-label&quot;&gt;Lower cost per deploy&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;stat-tile&quot; style=&quot;--accent: #C49BFF&quot;&gt;
  &lt;div class=&quot;stat-value&quot;&gt;90&lt;/div&gt;
  &lt;div class=&quot;stat-label&quot;&gt;Engineers on the platform org&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Median lead time from merge to production dropped from just under five days to a little over three:&lt;/p&gt;
&lt;div class=&quot;compare&quot; style=&quot;--accent: #A24BF5&quot;&gt;
  &lt;div class=&quot;compare-label&quot;&gt;Median lead time, merge to production&lt;/div&gt;
  &lt;div class=&quot;compare-track&quot;&gt;
    &lt;div class=&quot;compare-fill&quot; style=&quot;left: 57.97101449275364%; width: 28.985507246376798%;&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;compare-dot compare-dot--before&quot; style=&quot;left: 86.95652173913044%;&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;compare-dot compare-dot--after&quot; style=&quot;left: 57.97101449275364%;&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;compare-values&quot;&gt;
    &lt;span class=&quot;compare-value compare-value--before&quot;&gt;Before &lt;strong&gt;4.8 days&lt;/strong&gt;&lt;/span&gt;
    &lt;span class=&quot;compare-value compare-value--after&quot;&gt;After &lt;strong&gt;3.2 days&lt;/strong&gt;&lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Cost per deploy — engineer-hours burned on process rather than the change itself — came down by a bit more than a third. We left the pipeline-tracing setup running so the platform team can watch the number themselves instead of taking our word for it next quarter. Deploy frequency recovered steadily as each fix landed, not in one jump:&lt;/p&gt;
&lt;div class=&quot;line-chart&quot; style=&quot;--accent: #C49BFF&quot;&gt;
  &lt;div class=&quot;line-chart-head&quot;&gt;Wk 6: &lt;strong&gt;9 deploys/wk&lt;/strong&gt;&lt;/div&gt;
  &lt;div class=&quot;line-plot&quot;&gt;
    &lt;svg viewBox=&quot;0 0 100 100&quot; preserveAspectRatio=&quot;none&quot;&gt;
      &lt;polygon class=&quot;line-area&quot; points=&quot;0,100 0.0,71.01449275362319 20.0,71.01449275362319 40.0,61.35265700483092 60.0,42.028985507246375 80.0,22.705314009661834 100.0,13.043478260869563 100,100&quot; /&gt;
      &lt;polyline class=&quot;line-path&quot; points=&quot;0.0,71.01449275362319 20.0,71.01449275362319 40.0,61.35265700483092 60.0,42.028985507246375 80.0,22.705314009661834 100.0,13.043478260869563 &quot; /&gt;
    &lt;/svg&gt;
    &lt;div class=&quot;line-dot line-dot--muted&quot; style=&quot;left: 0.0%; top: 71.01449275362319%;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line-dot line-dot--muted&quot; style=&quot;left: 20.0%; top: 71.01449275362319%;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line-dot line-dot--muted&quot; style=&quot;left: 40.0%; top: 61.35265700483092%;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line-dot line-dot--muted&quot; style=&quot;left: 60.0%; top: 42.028985507246375%;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line-dot line-dot--muted&quot; style=&quot;left: 80.0%; top: 22.705314009661834%;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;line-dot &quot; style=&quot;left: 100.0%; top: 13.043478260869563%;&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;line-labels&quot;&gt;
    &lt;span&gt;Wk 1&lt;/span&gt;&lt;span&gt;Wk 2&lt;/span&gt;&lt;span&gt;Wk 3&lt;/span&gt;&lt;span&gt;Wk 4&lt;/span&gt;&lt;span&gt;Wk 5&lt;/span&gt;&lt;span&gt;Wk 6&lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The fix, in the end, was mostly deleting things: a meeting, a shared environment, a single point of failure in an approval chain. That&#39;s usually where it is.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What we actually check before an eval harness ships</title>
        <published>2025-11-04T00:00:00+00:00</published>
        <updated>2025-11-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            Agustina A
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://0xe8.com/blog/what-we-check-before-an-eval-harness-ships/"/>
        <id>https://0xe8.com/blog/what-we-check-before-an-eval-harness-ships/</id>
        
        <content type="html" xml:base="https://0xe8.com/blog/what-we-check-before-an-eval-harness-ships/">&lt;p&gt;Most eval harnesses we inherit on day one of an engagement are built to answer &quot;does this response sound plausible&quot; rather than &quot;did the model do the thing correctly.&quot; Those are different questions, and only one of them tells you whether it&#39;s safe to change the prompt, swap the model, or ship the next version.&lt;/p&gt;
&lt;p&gt;Before we trust an eval harness enough to gate a deploy on it, we run it through the same four checks every time.&lt;/p&gt;
&lt;h2 id=&quot;1-does-it-fail-on-cases-you-know-are-wrong&quot;&gt;1. Does it fail on cases you know are wrong?&lt;/h2&gt;
&lt;p&gt;The single most common problem: an eval set with no negative examples. If every case in the suite is a real, correctly-handled request, a harness that always returns a fixed canned answer can still score close to 100%. We seed at least a third of the set with inputs we know should fail — ambiguous requests, adversarial phrasing, cases the current model already gets wrong — specifically to confirm the scoring function can tell the difference.&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #F8F8F2; background-color: #282A36;&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color: #50FA7B;&quot;&gt; score&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #FFB86C;font-style: italic;&quot;&gt;response&lt;/span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #8BE9FD;font-style: italic;&quot;&gt; str&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span style=&quot;color: #FFB86C;font-style: italic;&quot;&gt; expected&lt;/span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;:&lt;/span&gt;&lt;span&gt; Expectation)&lt;/span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #8BE9FD;font-style: italic;&quot;&gt; float&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;    if&lt;/span&gt;&lt;span&gt; expected.must_contain&lt;/span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; and&lt;/span&gt;&lt;span&gt; expected.must_contain&lt;/span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; not in&lt;/span&gt;&lt;span&gt; response:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;    if&lt;/span&gt;&lt;span&gt; expected.must_refuse&lt;/span&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt; and not&lt;/span&gt;&lt;span&gt; looks_like_refusal(response):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color: #BD93F9;&quot;&gt; 0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #FF79C6;&quot;&gt;    return&lt;/span&gt;&lt;span&gt; semantic_similarity(response, expected.reference)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A surprising amount of &quot;eval harness&quot; code we see is just the last line of that function — pure semantic similarity against a reference answer, with no hard failure conditions above it. That catches drift in tone. It does not catch a model confidently returning the wrong account balance.&lt;/p&gt;
&lt;h2 id=&quot;2-is-the-eval-set-actually-yours&quot;&gt;2. Is the eval set actually yours?&lt;/h2&gt;
&lt;p&gt;Generic benchmarks tell you how a model performs on the internet&#39;s idea of your problem. They don&#39;t tell you how it performs on your actual traffic, which has its own weird distribution of edge cases: the customer who pastes in a support ticket instead of a question, the request in a language your prompt wasn&#39;t tuned for, the input that&#39;s technically valid JSON but structurally nonsense. We build the eval set from real logged requests — sanitized, but real — every time.&lt;/p&gt;
&lt;h2 id=&quot;3-does-a-regression-in-the-eval-mean-a-regression-for-users&quot;&gt;3. Does a regression in the eval mean a regression for users?&lt;/h2&gt;
&lt;p&gt;We run this one backwards: take a change everyone agrees made things worse — a prompt edit that was rolled back, a model downgrade that got reverted — and confirm the eval score actually drops when we replay it. If the harness doesn&#39;t notice a change that the team already knows was bad, it isn&#39;t measuring the thing that matters, no matter how good the pass rate looks.&lt;/p&gt;
&lt;h2 id=&quot;4-who-looks-at-the-failures&quot;&gt;4. Who looks at the failures?&lt;/h2&gt;
&lt;p&gt;An eval harness that reports a number to a dashboard nobody opens isn&#39;t a safety mechanism, it&#39;s a decoration. Before we sign off on one, there&#39;s a named person whose job includes reading the failing cases after every run, not just the aggregate score. Usually that turns up a category of failure the eval set doesn&#39;t cover yet, which goes back into check 2.&lt;/p&gt;
&lt;p&gt;None of this is exotic. It&#39;s the same instinct as a good test suite: assert on outcomes, not vibes, and make sure something fails when it&#39;s supposed to. The harness that survives all four checks is the one we&#39;re willing to gate a production deploy on. Most of what we&#39;re handed on day one survives one or two.&lt;/p&gt;
</content>
        
    </entry>
</feed>
