<?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: Aly Esmaeil</title>
    <description>The latest articles on DEV Community by Aly Esmaeil (@alyesmaeil).</description>
    <link>https://dev.to/alyesmaeil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3901393%2Fff55f2bf-eaef-4754-98c9-248672dd1b5d.png</url>
      <title>DEV Community: Aly Esmaeil</title>
      <link>https://dev.to/alyesmaeil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alyesmaeil"/>
    <language>en</language>
    <item>
      <title>How I Built a Rust CLI Tool That Beats POSIX diff (and Saved My CI/CD Pipelines)</title>
      <dc:creator>Aly Esmaeil</dc:creator>
      <pubDate>Tue, 28 Apr 2026 01:50:35 +0000</pubDate>
      <link>https://dev.to/alyesmaeil/how-i-built-a-rust-cli-tool-that-beats-posix-diff-and-saved-my-cicd-pipelines-1j0</link>
      <guid>https://dev.to/alyesmaeil/how-i-built-a-rust-cli-tool-that-beats-posix-diff-and-saved-my-cicd-pipelines-1j0</guid>
      <description>&lt;p&gt;We’ve all been there. It’s a Friday afternoon, a deployment just went out, and suddenly the production reporting service crashes. &lt;/p&gt;

&lt;p&gt;After an hour of frantic debugging, you find the culprit: a junior developer added a new AWS SES environment variable to the staging &lt;code&gt;.env&lt;/code&gt; file but forgot to notify the Ops team to add it to production.&lt;/p&gt;

&lt;p&gt;As a Cloud Operations Engineer, troubleshooting missing configurations across environments (dev, staging, prod) is my daily bread and butter. The standard approach? Just use &lt;code&gt;diff&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;But if you've ever tried to &lt;code&gt;diff&lt;/code&gt; &lt;code&gt;.env&lt;/code&gt; files or Key-Value configs, you know it quickly turns into a nightmare.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem with Standard &lt;code&gt;diff&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Standard &lt;code&gt;diff&lt;/code&gt; is a legend, but it operates purely on literal lines. It completely breaks down with configuration files because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Order doesn't matter, but &lt;code&gt;diff&lt;/code&gt; cares:&lt;/strong&gt; Secrets Managers (like AWS SSM or Vault) rarely preserve the order of keys when pulling configs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delimiters change:&lt;/strong&gt; PM2 might output variables using a &lt;code&gt;:&lt;/code&gt; delimiter, while standard &lt;code&gt;.env&lt;/code&gt; files use &lt;code&gt;=&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quoting styles differ:&lt;/strong&gt; Some tools wrap values in double quotes, while others leave them bare.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You &lt;em&gt;could&lt;/em&gt; write a bash script with &lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt;, and &lt;code&gt;awk&lt;/code&gt; to normalize everything before diffing, but doing that during a live incident is the last thing you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enter Qaren: A Semantic Config Diff Tool
&lt;/h3&gt;

&lt;p&gt;I needed a tool that natively understood Key-Value semantics. It needed to ignore order, ignore delimiter formats, and ignore quoting differences. And most importantly, &lt;strong&gt;it needed to be fast&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So, I built &lt;a href="https://github.com/qaren-cli/qaren" rel="noopener noreferrer"&gt;Qaren&lt;/a&gt; in &lt;strong&gt;Rust&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Qaren is a single ~1MB static binary that parses config files, understands their semantics, and outputs a beautiful, unified, colored diff showing exactly what is missing or changed. You can even run &lt;code&gt;qaren kv -g patch.env&lt;/code&gt; to automatically generate a patch file of the missing keys (with zero-trust secret masking).&lt;/p&gt;

&lt;h3&gt;
  
  
  The Performance Flex: Beating POSIX &lt;code&gt;diff&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;I wanted Qaren to be my daily driver, which meant it also needed to work perfectly as a fallback literal diff tool for massive log files or database dumps. &lt;/p&gt;

&lt;p&gt;Initially, my literal diff implementation was getting crushed by GNU POSIX &lt;code&gt;diff&lt;/code&gt;. Comparing two 328MB log files took Qaren 4.3 seconds, while &lt;code&gt;diff&lt;/code&gt; did it in 2.5s. &lt;/p&gt;

&lt;p&gt;After some profiling, I found the bottlenecks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eager &lt;code&gt;String&lt;/code&gt; allocation.&lt;/li&gt;
&lt;li&gt;Full UTF-8 validation via &lt;code&gt;read_to_string&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To fix this, I implemented a "fast path". When no ignore-flags (like ignore-case) are passed, Qaren bypasses UTF-8 validation entirely, reading the files as raw bytes (&lt;code&gt;std::fs::read&lt;/code&gt; into &lt;code&gt;&amp;amp;[u8]&lt;/code&gt;). I paired this with lazy iteration using the &lt;code&gt;similar&lt;/code&gt; crate and parallel directory traversal using &lt;code&gt;rayon&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Results?&lt;/strong&gt; It now consistently beats highly-optimized GNU &lt;code&gt;diff&lt;/code&gt; on massive files. &lt;/p&gt;

&lt;p&gt;Here are the &lt;code&gt;hyperfine&lt;/code&gt; benchmarks testing two 1.1GB directories:&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%2Fjynrsoz6xys0yx56jswf.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%2Fjynrsoz6xys0yx56jswf.png" alt="hyperfine test results" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: I use &lt;code&gt;--color&lt;/code&gt; flag to fair measurement as qaren colored by default&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And here is the 328MB single file stress test:&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%2F9zbmw6xt3m0xbkjbygx9.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%2F9zbmw6xt3m0xbkjbygx9.png" alt="hyperfine test results" width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Compare entire directory structures, identifying orphan files and differences in existing ones.&lt;/strong&gt;&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%2Fweijk12g0jxa74q8q0pk.gif" 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%2Fweijk12g0jxa74q8q0pk.gif" alt="compare dires" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exclude known dynamic or irrelevant keys from comparison.&lt;/strong&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%2Ffby61xqc5lewg1kynb8g.gif" 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%2Ffby61xqc5lewg1kynb8g.gif" alt="ignore-key" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Export results in machine-readable format for automation.&lt;/strong&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%2F2b79ahtcimdnachjcjcj.gif" 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%2F2b79ahtcimdnachjcjcj.gif" alt="output" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it out
&lt;/h3&gt;

&lt;p&gt;Building Qaren has been an incredible journey into systems programming and performance engineering in Rust. It's completely open-source, and I'd love for the community to tear the code apart, try it in your CI/CD pipelines, and let me know what you think.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/qaren-cli/qaren" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://qaren.me/" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful, a ⭐ on GitHub would mean the world to me! Let me know in the comments how you handle configuration drift in your environments&lt;/p&gt;

</description>
      <category>rust</category>
      <category>devops</category>
      <category>cli</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
