<?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: smplogs</title>
    <description>The latest articles on DEV Community by smplogs (@smplogs).</description>
    <link>https://dev.to/smplogs</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%2F3840468%2F13795613-e8a2-4032-8386-5909f17dfa5f.png</url>
      <title>DEV Community: smplogs</title>
      <link>https://dev.to/smplogs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/smplogs"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>smplogs</dc:creator>
      <pubDate>Thu, 09 Apr 2026 17:14:02 +0000</pubDate>
      <link>https://dev.to/smplogs/-93d</link>
      <guid>https://dev.to/smplogs/-93d</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/smplogs/i-used-ai-to-rewrite-my-entire-go-engine-in-rust-in-2-days-60-files-zero-shortcuts-3nfj" class="crayons-story__hidden-navigation-link"&gt;I used AI to rewrite my entire Go engine in Rust in 2 days. 60+ files, zero shortcuts.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/smplogs" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F3840468%2F13795613-e8a2-4032-8386-5909f17dfa5f.png" alt="smplogs profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/smplogs" class="crayons-story__secondary fw-medium m:hidden"&gt;
              smplogs
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                smplogs
                
              
              &lt;div id="story-author-preview-content-3477515" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/smplogs" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F3840468%2F13795613-e8a2-4032-8386-5909f17dfa5f.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;smplogs&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/smplogs/i-used-ai-to-rewrite-my-entire-go-engine-in-rust-in-2-days-60-files-zero-shortcuts-3nfj" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 9&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/smplogs/i-used-ai-to-rewrite-my-entire-go-engine-in-rust-in-2-days-60-files-zero-shortcuts-3nfj" id="article-link-3477515"&gt;
          I used AI to rewrite my entire Go engine in Rust in 2 days. 60+ files, zero shortcuts.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/rust"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;rust&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webassembly"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webassembly&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/smplogs/i-used-ai-to-rewrite-my-entire-go-engine-in-rust-in-2-days-60-files-zero-shortcuts-3nfj" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;10&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/smplogs/i-used-ai-to-rewrite-my-entire-go-engine-in-rust-in-2-days-60-files-zero-shortcuts-3nfj#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>I used AI to rewrite my entire Go engine in Rust in 2 days. 60+ files, zero shortcuts.</title>
      <dc:creator>smplogs</dc:creator>
      <pubDate>Thu, 09 Apr 2026 16:48:50 +0000</pubDate>
      <link>https://dev.to/smplogs/i-used-ai-to-rewrite-my-entire-go-engine-in-rust-in-2-days-60-files-zero-shortcuts-3nfj</link>
      <guid>https://dev.to/smplogs/i-used-ai-to-rewrite-my-entire-go-engine-in-rust-in-2-days-60-files-zero-shortcuts-3nfj</guid>
      <description>&lt;p&gt;A few weeks ago I had a working analysis engine written in Go, compiled to WASM. It worked. It was 60+ files, thousands of lines, battle-tested. And I decided to throw it all away and rewrite it in Rust.&lt;/p&gt;

&lt;p&gt;I did it in 2 days, with AI doing most of the heavy lifting.&lt;/p&gt;

&lt;p&gt;This is the honest account of how that went: what worked, what didn't, and whether the result was actually worth it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.smplogs.com" rel="noopener noreferrer"&gt;smplogs&lt;/a&gt; is a tool that analyzes AWS CloudWatch log exports entirely in your browser. The analysis engine is compiled to WASM and runs client-side. Logs never touch my server.&lt;/p&gt;

&lt;p&gt;The Go engine had been running in production for months. It handled Lambda, API Gateway, and ECS parsing. It had anomaly detection, log clustering, T-Digest streaming percentiles, cold start detection, and a full parity test suite. It wasn't small.&lt;/p&gt;

&lt;p&gt;55 Go source files. 17,000+ lines. All of it needed to produce byte-for-byte identical output to pass the parity tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why bother?
&lt;/h2&gt;

&lt;p&gt;Honest reasons, not post-hoc rationalization:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Speed.&lt;/strong&gt; No GC, no goroutine scheduler, and the zero-copy scanner meant the Rust engine ended up 3x(!!) times faster on the same files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The binary size.&lt;/strong&gt; The Go WASM binary was 4.2 MB. The Rust binary came in at 470 KB - over 9x smaller. For something that loads on every page visit, that's a meaningful difference in cold-load time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GC pauses.&lt;/strong&gt; Go has a garbage collector. In a browser tab, GC pauses show up as UI jank when analyzing large files. Rust has no GC that makes latency predictable from start to finish.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory.&lt;/strong&gt; The Go engine's WASM target uses the standard Go runtime which brings in a full garbage collector and goroutine scheduler - overhead you pay even for a single-threaded WASM module. The Rust build is lean: only what you explicitly use ends up in the binary.&lt;/p&gt;

&lt;p&gt;Those were the real reasons. I could also say "I wanted to learn Rust better," which is true, but let's be real, that's not why you rewrite production code.&lt;/p&gt;




&lt;h2&gt;
  
  
  The approach: one phase at a time
&lt;/h2&gt;

&lt;p&gt;I didn't try to rewrite everything at once. I broke it into 8 phases and did one per session with Claude:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Phase 1 — Foundation: types, parser, basic lib.rs scaffolding
Phase 2 — Core accumulation: service detection, metrics
Phase 3 — Findings, risk scoring, anomaly, clustering, correlation
Phase 4 — API Gateway + ECS parsers, finalize dispatch, parity tests
Phase 5 — Session validation, T-Digest streaming, smplogs_analyze
Phase 6 — Frontend dual-engine loader (Rust primary, Go fallback)
Phase 7 — Zero-copy chunk scanner, enhanced WASM bindings
Phase 8 — Final migration: drop Go entirely, Rust-only CI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each phase had one clear deliverable: build passes, parity tests pass against Go's golden output, move on.&lt;/p&gt;

&lt;p&gt;The key thing I told Claude at the start of each session: "Mirror the Go implementation exactly. Same logic, same thresholds, same output format. Don't improve it. Don't optimize it. Just port it." That instruction saved a lot of pain. Every time AI tried to "improve" a threshold or restructure a calculation, the parity tests caught it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What AI was good for
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Mechanical translation.&lt;/strong&gt; Go struct → Rust struct, Go method → Rust function. The Go code was clean and well-commented, which made this straightforward. Claude would take a 300-line Go file and produce a correct Rust port in one shot. Not perfect, but close enough that a short review + test run caught the rest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lifetime annotations.&lt;/strong&gt; I would have spent days figuring out the right lifetime bounds for the zero-copy scanner. The signature looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;scan_chunk&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;on_event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;FnMut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;i64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;'a&lt;/code&gt; on the closure parameter, meaning "the &lt;code&gt;&amp;amp;str&lt;/code&gt; slices you receive are borrowed from &lt;code&gt;src&lt;/code&gt; and live as long as &lt;code&gt;src&lt;/code&gt;" is exactly the kind of thing that takes Rust beginners a while to reason through. Claude got it right on the first try, and more importantly, explained &lt;em&gt;why&lt;/em&gt; it was correct.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Boilerplate.&lt;/strong&gt; wasm-bindgen exports, &lt;code&gt;#[cfg(target_arch = "wasm32")]&lt;/code&gt; conditional compilation, Cargo.toml feature flags - all stuff that's tedious and error-prone to write by hand. AI handled all of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;T-Digest port.&lt;/strong&gt; The Go T-Digest implementation was non-trivial. Porting it to Rust and maintaining the exact centroid compression algorithm, the quantile interpolation, the &lt;code&gt;seed_from_sorted&lt;/code&gt; transition path would have taken me a full day alone. With AI it took about an hour, including fixing a subtle off-by-one in the &lt;code&gt;compress_static&lt;/code&gt; function.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where it got tricky
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Parity failures.&lt;/strong&gt; This was the main source of friction. The Go engine had accumulated edge case handling over months of production use. Things like: timestamps sometimes come as quoted strings in CloudWatch exports. The Go code handled it silently. The Rust port didn't, until I added the same handling. Parity tests caught every single one of these, which is why writing them first was the right call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;unsafe&lt;/code&gt; blocks.&lt;/strong&gt; WASM is single-threaded but Rust's borrow checker doesn't know that. Static mutable state (&lt;code&gt;INCR_STATE&lt;/code&gt;, &lt;code&gt;INPUT_BUF&lt;/code&gt;, &lt;code&gt;DOMAIN_CANARY&lt;/code&gt;) requires &lt;code&gt;unsafe&lt;/code&gt;. Claude was correct about when &lt;code&gt;unsafe&lt;/code&gt; was needed, but I made sure to review every single one. I wasn't going to ship &lt;code&gt;unsafe&lt;/code&gt; I didn't understand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;wasm-bindgen error messages.&lt;/strong&gt; When you get a type wrong at the JS&amp;lt;-&amp;gt;Rust boundary, the error is sometimes just &lt;code&gt;unreachable executed&lt;/code&gt; in WASM: no stack trace, no type info. This isn't AI's fault, it's just the toolchain, but it meant debugging sessions that AI couldn't help with because there was no error message to analyze.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Windows build.&lt;/strong&gt; &lt;code&gt;wasm-pack&lt;/code&gt; works, but getting &lt;code&gt;wasm-bindgen-cli&lt;/code&gt; at exactly the right version to match &lt;code&gt;wasm-bindgen&lt;/code&gt; in &lt;code&gt;Cargo.toml&lt;/code&gt; on Windows took an embarrassing amount of time. I ended up with a &lt;code&gt;build.ps1&lt;/code&gt; that handles the version dance explicitly.&lt;/p&gt;




&lt;h2&gt;
  
  
  The zero-copy scanner (the one thing I pushed for)
&lt;/h2&gt;

&lt;p&gt;Once the basic port was done and parity tests passed, I asked Claude to go further on one specific thing: memory.&lt;/p&gt;

&lt;p&gt;The original Go engine used &lt;code&gt;encoding/json&lt;/code&gt; to parse CloudWatch exports. That allocates a string per log event were fine in Go, painful in WASM where every allocation lives forever (WASM linear memory never shrinks). With 500K events in a file, you're doing 500K allocations for strings you inspect for a millisecond.&lt;/p&gt;

&lt;p&gt;The Rust port initially did the same with &lt;code&gt;serde_json&lt;/code&gt;. I asked Claude to write a custom scanner that walks the raw bytes and returns borrowed slices instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;scan_chunk&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;on_event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;FnMut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;i64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// walk src as bytes, locate "logEvents" array&lt;/span&gt;
    &lt;span class="c1"&gt;// for each object: parse timestamp, return &amp;amp;str slice for message&lt;/span&gt;
    &lt;span class="c1"&gt;// no String allocated — caller gets a pointer into src&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The insight that made it work: Lambda control lines (&lt;code&gt;START&lt;/code&gt;, &lt;code&gt;END&lt;/code&gt;, &lt;code&gt;REPORT&lt;/code&gt;) are plain ASCII. You can check &lt;code&gt;starts_with(b"REPORT")&lt;/code&gt; on raw bytes without decoding JSON escape sequences. The only time we need to decode is when storing the first log line of an invocation for display - which happens once per invocation, not once per event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;before: 1GB file -&amp;gt; ~2GB peak memory (string-per-event)
after:  1GB file -&amp;gt; ~50MB peak memory (borrowed slices)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was a legitimate collaboration: I knew what I wanted, I could describe the constraint (escape sequences, ASCII prefixes), and Claude wrote the implementation. I reviewed it, understood it, and it's now in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  The result in numbers
&lt;/h2&gt;

&lt;p&gt;Final migration commit stats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;68 files changed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;17,952 lines deleted&lt;/strong&gt; (Go engine, Go tests, Go bridge, wasm_exec.js)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;~180 lines added&lt;/strong&gt; (mostly CI and build script changes, the Rust was already done in prior commits)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Binary: 4.2 MB →-&amp;gt;470 KB&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;3x faster analysis&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;All parity tests passing&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 8 phases took roughly 2 days of focused work. Not 2 days of AI running autonomously but rather 2 days of me directing, reviewing, running tests, and debugging the gaps. The AI probably saved me 2–3 weeks of solo work.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I actually learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AI is good at translation, not design.&lt;/strong&gt; The Go engine had years of design decisions baked in: thresholds, error handling, data structures. Those decisions came from production experience. AI can port them, but it can't create them from scratch. The port worked because the design already existed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parity tests are the whole game.&lt;/strong&gt; Without a golden-output test suite to compare against, I would have had no confidence the Rust engine was correct. Every time a parity test failed, it pointed directly at the divergence. Write parity tests before you start any migration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Don't improve it" is the right instruction.&lt;/strong&gt; Every unsolicited improvement AI made introduced a parity failure. The instruction "port this exactly, don't optimize" was the single most useful constraint I set.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Review everything with &lt;code&gt;unsafe&lt;/code&gt;.&lt;/strong&gt; AI got the &lt;code&gt;unsafe&lt;/code&gt; blocks right, but I still read every one. That's not paranoia, it's the deal you make when you use &lt;code&gt;unsafe&lt;/code&gt; in production code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is it worth it?
&lt;/h2&gt;

&lt;p&gt;For me: yes. The engine is way faster, binary is 2.5x smaller, GC pauses are gone, and I now have a Rust codebase I can extend in ways the Go WASM target wouldn't have allowed (zero-copy scanner, T-Digest streaming transition, reusable input buffers).&lt;/p&gt;

&lt;p&gt;Would I do it without AI? Probably not on that timeline. The mechanical translation work: porting 50 files of Go to idiomatic Rust would have been a month-long project, not a 2-day one.&lt;/p&gt;

&lt;p&gt;The thing I'd tell anyone considering a similar migration: AI does the typing, you do the thinking. You need to understand the source code well enough to know when the port is wrong. If you're treating it as "AI will handle it," you'll end up with a codebase you can't debug.&lt;/p&gt;




&lt;p&gt;If you want to see the result, &lt;a href="https://www.smplogs.com" rel="noopener noreferrer"&gt;smplogs.com&lt;/a&gt; runs the Rust engine. Free plan gets you 3 analyses/day - upload a CloudWatch export or use the extension directly from AWS Events and see what it finds. The browser extension also lets you analyze directly from the AWS Console without exporting anything.&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the migration in the comments - especially if you've done something similar with a large Go or Python codebase.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>webassembly</category>
      <category>showdev</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
