<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Case Study on BXM.net</title>
    <link>https://bxm.net/tags/case-study/</link>
    <description>Recent content in Case Study on BXM.net</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 22 Oct 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://bxm.net/tags/case-study/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>A Config Diff of 128 Lines Hid Two Real Changes, and Canon Named Both in Two Lines</title>
      <link>https://bxm.net/a-config-diff-of-128-lines-hid-two-real-changes-and-canon-named-both-in-two-lines/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/a-config-diff-of-128-lines-hid-two-real-changes-and-canon-named-both-in-two-lines/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s a familiar review. The config for a checkout service comes back from someone&amp;rsquo;s editor and the diff is a wall of red and green. The editor saved with four spaces instead of two, sorted the keys, and escaped the &amp;ldquo;ü&amp;rdquo; in the description. Somewhere in there, maybe, a value changed.&lt;/p&gt;&#xA;&lt;p&gt;We built that situation on purpose. One service config of 66 lines covers the server, database, cache, limits, features, logging and deploy settings. The deploy tool writes it one way. An editor saves it another way and changes two values on the way: the database pool timeout drops from 30000 ms to 3000 ms, and the replica count turns from the integer &lt;code&gt;3&lt;/code&gt; into the float &lt;code&gt;3.0&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hashing 100,000 JSON Lines Found No Duplicates, Hashing Them With Canon Found 9,900</title>
      <link>https://bxm.net/hashing-100000-json-lines-found-no-duplicates-hashing-them-with-canon-found-9900/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/hashing-100000-json-lines-found-no-duplicates-hashing-them-with-canon-found-9900/</guid>
      <description>&lt;p&gt;Event pipelines get the same event twice. A producer times out, retries, and the retry goes through a different service that writes JSON its own way. The usual dedupe is a hash of each line, and it quietly misses all of these.&lt;/p&gt;&#xA;&lt;p&gt;We generated a stream of 100,000 JSON lines from a fixed seed, 13.1 MB in all. 90,000 are distinct purchase events. The other 10,000 are resends of earlier events, written by two other producers. One sorts the keys and escapes non-ASCII, so &amp;ldquo;Zürich&amp;rdquo; arrives as &lt;code&gt;Z\u00fcrich&lt;/code&gt;. The other reverses the key order and adds spaces. For a twist, 100 of the resends come from a producer that writes the quantity as a float: &lt;code&gt;2.0&lt;/code&gt; where the original said &lt;code&gt;2&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Memo in GitHub Actions Skipped a Rust Release Build and Caught Runners With Different Compilers</title>
      <link>https://bxm.net/memo-in-github-actions-skipped-a-rust-release-build-and-caught-runners-with-different-compilers/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/memo-in-github-actions-skipped-a-rust-release-build-and-caught-runners-with-different-compilers/</guid>
      <description>&lt;p&gt;Most CI jobs build the same thing again and again. A docs fix or a typo in a README triggers the whole pipeline, and the release build runs as if the code had changed. This case study puts BXM Memo in front of one such step, a release build of the &lt;code&gt;bxm-canon&lt;/code&gt; binary, and keeps Memo&amp;rsquo;s cache between jobs with &lt;code&gt;actions/cache&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The workflow is in the &lt;a href=&#34;https://github.com/softdevstudio/bxm&#34;&gt;repository&lt;/a&gt; as &lt;code&gt;.github/workflows/case-study-memo.yml&lt;/code&gt;. Five jobs run one after another, each on a fresh GitHub-hosted runner. &lt;code&gt;plain&lt;/code&gt; builds without Memo for the baseline. &lt;code&gt;cold&lt;/code&gt; builds through Memo with an empty cache, &lt;code&gt;warm&lt;/code&gt; changes nothing, &lt;code&gt;docs&lt;/code&gt; edits the README, and &lt;code&gt;source&lt;/code&gt; edits a Rust source file. The inputs are &lt;code&gt;canon/src/**&lt;/code&gt;, &lt;code&gt;Cargo.toml&lt;/code&gt; and &lt;code&gt;Cargo.lock&lt;/code&gt;, and the salt is &lt;code&gt;rustc --version&lt;/code&gt;, so a different compiler means a different result. We ran the whole workflow twice.&lt;/p&gt;</description>
    </item>
    <item>
      <title>One Order Built in Python, JavaScript and by Hand Gives Three JSON Hashes and One Canon Hash</title>
      <link>https://bxm.net/one-order-built-in-python-javascript-and-by-hand-gives-three-json-hashes-and-one-canon-hash/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/one-order-built-in-python-javascript-and-by-hand-gives-three-json-hashes-and-one-canon-hash/</guid>
      <description>&lt;p&gt;A checkout service written in Python signs each order before it hands it on. A fulfilment service written in JavaScript checks the signature before it ships anything. Both have the same order in memory. The question is whether they agree on its bytes.&lt;/p&gt;&#xA;&lt;p&gt;We built one order three ways. Python filled a dict in the order its code reads, and &lt;code&gt;json.dumps&lt;/code&gt; wrote it with its defaults: a space after every comma and colon, and &amp;ldquo;Zürich&amp;rdquo; escaped as &lt;code&gt;Z\u00fcrich&lt;/code&gt;. JavaScript built the same object with its keys in another order, and &lt;code&gt;JSON.stringify&lt;/code&gt; wrote it compactly with the ü left as it is. The third copy is a file written by hand, pretty-printed, with yet another key order, hashed with the &lt;code&gt;bxm-canon&lt;/code&gt; command.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Replaying 13 Commits Through Memo Cut Test Time From 228 to 79 Seconds and Turned Up Two Flaky Tests</title>
      <link>https://bxm.net/replaying-13-commits-through-memo-cut-test-time-from-228-to-79-seconds-and-turned-up-two-flaky-tests/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/replaying-13-commits-through-memo-cut-test-time-from-228-to-79-seconds-and-turned-up-two-flaky-tests/</guid>
      <description>&lt;p&gt;BXM&amp;rsquo;s repository has two packages with their own test suites: Canon, tested with &lt;code&gt;cargo test&lt;/code&gt;, and Memo, tested with &lt;code&gt;go test&lt;/code&gt;. Most commits touch one of them, or neither. A docs change or a new JavaScript build script doesn&amp;rsquo;t change either suite&amp;rsquo;s result, yet a plain CI job runs both every time.&lt;/p&gt;&#xA;&lt;p&gt;So we replayed the repository&amp;rsquo;s own history. All 13 commits from 0.1.0 to the end of 0.3.0 were checked out one after another, and both suites ran at each one. That happened twice: once plain, and once with each suite behind Memo. Canon&amp;rsquo;s suite takes &lt;code&gt;canon/**&lt;/code&gt; and the spec&amp;rsquo;s test vectors as inputs. Memo&amp;rsquo;s takes &lt;code&gt;memo/**&lt;/code&gt;. Memo needs a declared output, so each suite writes its log to a file and that file is the output.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why Did My Build Step Run Again, Six Cache Misses and What Memo Said About Each</title>
      <link>https://bxm.net/why-did-my-build-step-run-again-six-cache-misses-and-what-memo-said-about-each/</link>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <guid>https://bxm.net/why-did-my-build-step-run-again-six-cache-misses-and-what-memo-said-about-each/</guid>
      <description>&lt;p&gt;A cache that misses without saying why is almost as annoying as no cache. Someone notices the step ran again, nobody knows why, and the cache key gets a random suffix &amp;ldquo;to be safe&amp;rdquo;. After that the cache never hits.&lt;/p&gt;&#xA;&lt;p&gt;BXM Memo keeps the manifest of the last run of each named job. On a miss it compares the two and says what changed. We put that to work on a small report step: a Python script that totals sales per region from monthly CSV files into &lt;code&gt;out/report.txt&lt;/code&gt;. The step runs through Memo with the script and &lt;code&gt;data/*.csv&lt;/code&gt; as inputs, &lt;code&gt;REPORT_CURRENCY&lt;/code&gt; as an environment variable that changes the result, and the Python version as the salt.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
